openmp: Handle lastprivate on combined target correctly [PR99928]
authorJakub Jelinek <jakub@redhat.com>
Wed, 19 May 2021 07:21:09 +0000 (09:21 +0200)
committerJakub Jelinek <jakub@redhat.com>
Wed, 19 May 2021 07:30:03 +0000 (09:30 +0200)
This patch deals with 2 issues:
1) the gimplifier couldn't differentiate between
 #pragma omp parallel master
 #pragma omp taskloop simd
and
 #pragma omp parallel master taskloop simd
when there is a significant difference for clause handling between
the two; as master construct doesn't have any clauses, we don't currently
represent it during gimplification by an gimplification omp context at all,
so this patch makes sure we don't set OMP_PARALLEL_COMBINED on parallel master
when not combined further.  If we ever add a separate master context during
gimplification, we'd use ORT_COMBINED_MASTER vs. ORT_MASTER (or MASKED probably).
2) lastprivate when combined with target should be map(tofrom:) on the target,
this change handles it only when not combined with firstprivate though, that
will need further work (similarly to linear or reduction).

2021-05-19  Jakub Jelinek  <jakub@redhat.com>

PR middle-end/99928
gcc/
* tree.h (OMP_MASTER_COMBINED): Define.
* gimplify.c (gimplify_scan_omp_clauses): Rewrite lastprivate
handling for outer combined/composite constructs to a loop.
Handle lastprivate on combined target.
(gimplify_expr): Formatting fix.
gcc/c/
* c-parser.c (c_parser_omp_master): Set OMP_MASTER_COMBINED on
master when combined with taskloop.
(c_parser_omp_parallel): Don't set OMP_PARALLEL_COMBINED on
parallel master when not combined with taskloop.
gcc/cp/
* parser.c (cp_parser_omp_master): Set OMP_MASTER_COMBINED on
master when combined with taskloop.
(cp_parser_omp_parallel): Don't set OMP_PARALLEL_COMBINED on
parallel master when not combined with taskloop.
gcc/testsuite/
* c-c++-common/gomp/pr99928-2.c: Remove all xfails.
* c-c++-common/gomp/pr99928-12.c: New test.

gcc/c/c-parser.c
gcc/cp/parser.c
gcc/gimplify.c
gcc/testsuite/c-c++-common/gomp/pr99928-12.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/gomp/pr99928-2.c
gcc/tree.h

index f79b839..b9930d4 100644 (file)
@@ -18826,6 +18826,7 @@ c_parser_omp_master (location_t loc, c_parser *parser,
          if (ret == NULL_TREE)
            return ret;
          ret = c_finish_omp_master (loc, block);
+         OMP_MASTER_COMBINED (ret) = 1;
          return ret;
        }
     }
@@ -19126,7 +19127,16 @@ c_parser_omp_parallel (location_t loc, c_parser *parser,
                                        block);
          if (ret == NULL)
            return ret;
-         OMP_PARALLEL_COMBINED (stmt) = 1;
+         /* master doesn't have any clauses and during gimplification
+            isn't represented by a gimplification omp context, so for
+            #pragma omp parallel master don't set OMP_PARALLEL_COMBINED,
+            so that
+            #pragma omp parallel master
+            #pragma omp taskloop simd lastprivate (x)
+            isn't confused with
+            #pragma omp parallel master taskloop simd lastprivate (x)  */
+         if (OMP_MASTER_COMBINED (ret))
+           OMP_PARALLEL_COMBINED (stmt) = 1;
          return stmt;
        }
       else if (strcmp (p, "loop") == 0)
index c0b5795..f3503b1 100644 (file)
@@ -40922,7 +40922,9 @@ cp_parser_omp_master (cp_parser *parser, cp_token *pragma_tok,
          tree body = finish_omp_structured_block (sb);
          if (ret == NULL)
            return ret;
-         return c_finish_omp_master (loc, body);
+         ret = c_finish_omp_master (loc, body);
+         OMP_MASTER_COMBINED (ret) = 1;
+         return ret;
        }
     }
   if (!flag_openmp)  /* flag_openmp_simd  */
@@ -41206,7 +41208,16 @@ cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok,
                                      block);
          if (ret == NULL_TREE)
            return ret;
-         OMP_PARALLEL_COMBINED (stmt) = 1;
+         /* master doesn't have any clauses and during gimplification
+            isn't represented by a gimplification omp context, so for
+            #pragma omp parallel master don't set OMP_PARALLEL_COMBINED,
+            so that
+            #pragma omp parallel master
+            #pragma omp taskloop simd lastprivate (x)
+            isn't confused with
+            #pragma omp parallel master taskloop simd lastprivate (x)  */
+         if (OMP_MASTER_COMBINED (ret))
+           OMP_PARALLEL_COMBINED (stmt) = 1;
          return stmt;
        }
       else if (strcmp (p, "loop") == 0)
index e790f08..2730f22 100644 (file)
@@ -8642,75 +8642,48 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
            }
          if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
            flags |= GOVD_LASTPRIVATE_CONDITIONAL;
-         if (outer_ctx
-             && (outer_ctx->region_type == ORT_COMBINED_PARALLEL
-                 || ((outer_ctx->region_type & ORT_COMBINED_TEAMS)
-                     == ORT_COMBINED_TEAMS))
-             && splay_tree_lookup (outer_ctx->variables,
-                                   (splay_tree_key) decl) == NULL)
-           {
-             omp_add_variable (outer_ctx, decl, GOVD_SHARED | GOVD_SEEN);
-             if (outer_ctx->outer_context)
-               omp_notice_variable (outer_ctx->outer_context, decl, true);
-           }
-         else if (outer_ctx
-                  && (outer_ctx->region_type & ORT_TASK) != 0
-                  && outer_ctx->combined_loop
-                  && splay_tree_lookup (outer_ctx->variables,
-                                        (splay_tree_key) decl) == NULL)
-           {
-             omp_add_variable (outer_ctx, decl, GOVD_LASTPRIVATE | GOVD_SEEN);
-             if (outer_ctx->outer_context)
-               omp_notice_variable (outer_ctx->outer_context, decl, true);
-           }
-         else if (outer_ctx
-                  && (outer_ctx->region_type == ORT_WORKSHARE
-                      || outer_ctx->region_type == ORT_ACC)
-                  && outer_ctx->combined_loop
-                  && splay_tree_lookup (outer_ctx->variables,
-                                        (splay_tree_key) decl) == NULL
-                  && !omp_check_private (outer_ctx, decl, false))
-           {
-             omp_add_variable (outer_ctx, decl, GOVD_LASTPRIVATE | GOVD_SEEN);
-             if (outer_ctx->outer_context
-                 && (outer_ctx->outer_context->region_type
-                     == ORT_COMBINED_PARALLEL)
-                 && splay_tree_lookup (outer_ctx->outer_context->variables,
+         struct gimplify_omp_ctx *octx;
+         for (octx = outer_ctx; octx; octx = octx->outer_context)
+           {
+             if ((octx->region_type == ORT_COMBINED_PARALLEL
+                  || ((octx->region_type & ORT_COMBINED_TEAMS)
+                       == ORT_COMBINED_TEAMS))
+                 && splay_tree_lookup (octx->variables,
                                        (splay_tree_key) decl) == NULL)
                {
-                 struct gimplify_omp_ctx *octx = outer_ctx->outer_context;
                  omp_add_variable (octx, decl, GOVD_SHARED | GOVD_SEEN);
-                 if (octx->outer_context)
-                   {
-                     octx = octx->outer_context;
-                     if (octx->region_type == ORT_WORKSHARE
-                         && octx->combined_loop
-                         && splay_tree_lookup (octx->variables,
-                                               (splay_tree_key) decl) == NULL
-                         && !omp_check_private (octx, decl, false))
-                       {
-                         omp_add_variable (octx, decl,
-                                           GOVD_LASTPRIVATE | GOVD_SEEN);
-                         octx = octx->outer_context;
-                         if (octx
-                             && ((octx->region_type & ORT_COMBINED_TEAMS)
-                                 == ORT_COMBINED_TEAMS)
-                             && (splay_tree_lookup (octx->variables,
-                                                    (splay_tree_key) decl)
-                                 == NULL))
-                           {
-                             omp_add_variable (octx, decl,
-                                               GOVD_SHARED | GOVD_SEEN);
-                             octx = octx->outer_context;
-                           }
-                       }
-                     if (octx)
-                       omp_notice_variable (octx, decl, true);
-                   }
+                 continue;
                }
-             else if (outer_ctx->outer_context)
-               omp_notice_variable (outer_ctx->outer_context, decl, true);
+             if ((octx->region_type & ORT_TASK) != 0
+                 && octx->combined_loop
+                 && splay_tree_lookup (octx->variables,
+                                       (splay_tree_key) decl) == NULL)
+               {
+                 omp_add_variable (octx, decl, GOVD_LASTPRIVATE | GOVD_SEEN);
+                 continue;
+               }
+             if ((octx->region_type == ORT_WORKSHARE
+                  || octx->region_type == ORT_ACC)
+                 && octx->combined_loop
+                 && splay_tree_lookup (octx->variables,
+                                       (splay_tree_key) decl) == NULL
+                 && !omp_check_private (octx, decl, false))
+               {
+                 omp_add_variable (octx, decl, GOVD_LASTPRIVATE | GOVD_SEEN);
+                 continue;
+               }
+             if (octx->region_type == ORT_COMBINED_TARGET
+                 && splay_tree_lookup (octx->variables,
+                                       (splay_tree_key) decl) == NULL)
+               {
+                 omp_add_variable (octx, decl, GOVD_MAP | GOVD_SEEN);
+                 octx = octx->outer_context;
+                 break;
+               }
+             break;
            }
+         if (octx && octx != outer_ctx)
+           omp_notice_variable (octx, decl, true);
          goto do_add;
        case OMP_CLAUSE_REDUCTION:
          if (OMP_CLAUSE_REDUCTION_TASK (c))
@@ -14643,7 +14616,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
                g = gimple_build_omp_section (body);
                break;
              case OMP_MASTER:
-               g = gimple_build_omp_master (body);
+               g = gimple_build_omp_master (body);
                break;
              case OMP_ORDERED:
                g = gimplify_omp_ordered (*expr_p, body);
diff --git a/gcc/testsuite/c-c++-common/gomp/pr99928-12.c b/gcc/testsuite/c-c++-common/gomp/pr99928-12.c
new file mode 100644 (file)
index 0000000..be0c5c0
--- /dev/null
@@ -0,0 +1,23 @@
+/* PR middle-end/99928 */
+/* { dg-do compile } */
+
+int
+foo (void)
+{
+  int l = 0;
+  #pragma omp parallel master taskloop simd lastprivate (l) default(none)      /* { dg-bogus "'l' not specified in enclosing 'parallel'" } */
+  for (int i = 0; i < 16; i++)
+    l = i;
+  return l;
+}
+
+int
+bar (void)
+{
+  int l = 0;
+  #pragma omp parallel master default(none)    /* { dg-message "enclosing 'parallel'" } */
+  #pragma omp taskloop simd lastprivate (l)    /* { dg-error "'l' not specified in enclosing 'parallel'" } */
+  for (int i = 0; i < 16; i++)
+    l = i;
+  return l;
+}
index 313374c..6ba3d46 100644 (file)
@@ -92,38 +92,38 @@ bar (void)
     #pragma omp section
     l10 = 2;
   }
-  /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:l11" "gimple" { xfail *-*-* } } } */
-  /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(l11\\)" "gimple" { xfail *-*-* } } } */
+  /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:l11" "gimple" } } */
+  /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(l11\\)" "gimple" } } */
   /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(l11\\)" "gimple" } } *//* FIXME: This should be on for instead.  */
   /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(l11\\)" "gimple" } } *//* FIXME.  */
   #pragma omp target parallel for lastprivate (l11)
   for (int i = 0; i < 64; i++)
     l11 = i;
-  /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:l12" "gimple" { xfail *-*-* } } } */
-  /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(l12\\)" "gimple" { xfail *-*-* } } } */
+  /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:l12" "gimple" } } */
+  /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(l12\\)" "gimple" } } */
   /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(l12\\)" "gimple" } } *//* FIXME: This should be on for instead.  */
   /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(l12\\)" "gimple" } } *//* FIXME.  */
   /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(l12\\)" "gimple" } } */
   #pragma omp target parallel for simd lastprivate (l12)
   for (int i = 0; i < 64; i++)
     l12 = i;
-  /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:j01" "gimple" { xfail *-*-* } } } */
-  /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(j01\\)" "gimple" { xfail *-*-* } } } */
+  /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:j01" "gimple" } } */
+  /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(j01\\)" "gimple" } } */
   /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*shared\\(j01\\)" "gimple" } } */
   /* { dg-final { scan-tree-dump "omp for\[^\n\r]*lastprivate\\(j01\\)" "gimple" } } *//* NOTE: This is implementation detail.  */
   /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(j01\\)" "gimple" } } *//* NOTE: This is implementation detail.  */
   #pragma omp target parallel loop lastprivate (j01)
   for (j01 = 0; j01 < 64; j01++)
     ;
-  /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:l13" "gimple" { xfail *-*-* } } } */
-  /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(l13\\)" "gimple" { xfail *-*-* } } } */
+  /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:l13" "gimple" } } */
+  /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(l13\\)" "gimple" } } */
   /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*shared\\(l13\\)" "gimple" } } */
   /* { dg-final { scan-tree-dump "omp distribute\[^\n\r]*lastprivate\\(l13\\)" "gimple" } } */
   #pragma omp target teams distribute lastprivate (l13)
   for (int i = 0; i < 64; i++)
     l13 = i;
-  /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:l14" "gimple" { xfail *-*-* } } } */
-  /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(l14\\)" "gimple" { xfail *-*-* } } } */
+  /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:l14" "gimple" } } */
+  /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(l14\\)" "gimple" } } */
   /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*shared\\(l14\\)" "gimple" } } */
   /* { dg-final { scan-tree-dump "omp distribute\[^\n\r]*lastprivate\\(l14\\)" "gimple" } } */
   /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(l14\\)" "gimple" } } *//* FIXME: This should be on for instead.  */
@@ -131,8 +131,8 @@ bar (void)
   #pragma omp target teams distribute parallel for lastprivate (l14)
   for (int i = 0; i < 64; i++)
     l14 = i;
-  /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:l15" "gimple" { xfail *-*-* } } } */
-  /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(l15\\)" "gimple" { xfail *-*-* } } } */
+  /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:l15" "gimple" } } */
+  /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(l15\\)" "gimple" } } */
   /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*shared\\(l15\\)" "gimple" } } */
   /* { dg-final { scan-tree-dump "omp distribute\[^\n\r]*lastprivate\\(l15\\)" "gimple" } } */
   /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(l15\\)" "gimple" } } *//* FIXME: This should be on for instead.  */
@@ -141,16 +141,16 @@ bar (void)
   #pragma omp target teams distribute parallel for simd lastprivate (l15)
   for (int i = 0; i < 64; i++)
     l15 = i;
-  /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:l16" "gimple" { xfail *-*-* } } } */
-  /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(l16\\)" "gimple" { xfail *-*-* } } } */
+  /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:l16" "gimple" } } */
+  /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(l16\\)" "gimple" } } */
   /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*shared\\(l16\\)" "gimple" } } */
   /* { dg-final { scan-tree-dump "omp distribute\[^\n\r]*lastprivate\\(l16\\)" "gimple" } } */
   /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(l16\\)" "gimple" } } */
   #pragma omp target teams distribute simd lastprivate (l16)
   for (int i = 0; i < 64; i++)
     l16 = i;
-  /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:j02" "gimple" { xfail *-*-* } } } */
-  /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(j02\\)" "gimple" { xfail *-*-* } } } */
+  /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:j02" "gimple" } } */
+  /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(j02\\)" "gimple" } } */
   /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*shared\\(j02\\)" "gimple" } } */
   /* { dg-final { scan-tree-dump "omp distribute\[^\n\r]*lastprivate\\(j02\\)" "gimple" } } *//* NOTE: This is implementation detail.  */
   /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*shared\\(j02\\)" "gimple" } } *//* NOTE: This is implementation detail.  */
@@ -159,8 +159,8 @@ bar (void)
   #pragma omp target teams loop lastprivate (j02)
   for (j02 = 0; j02 < 64; j02++)
     ;
-  /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:l17" "gimple" { xfail *-*-* } } } */
-  /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(l17\\)" "gimple" { xfail *-*-* } } } */
+  /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:l17" "gimple" } } */
+  /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(l17\\)" "gimple" } } */
   /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(l17\\)" "gimple" } } */
   #pragma omp target simd lastprivate (l17)
   for (int i = 0; i < 64; i++)
index 784452c..64612cf 100644 (file)
@@ -1502,6 +1502,11 @@ class auto_suppress_location_wrappers
 #define OMP_TARGET_COMBINED(NODE) \
   (OMP_TARGET_CHECK (NODE)->base.private_flag)
 
+/* True on an OMP_MASTER statement if it represents an explicit
+   combined master constructs.  */
+#define OMP_MASTER_COMBINED(NODE) \
+  (OMP_MASTER_CHECK (NODE)->base.private_flag)
+
 /* Memory order for OMP_ATOMIC*.  */
 #define OMP_ATOMIC_MEMORY_ORDER(NODE) \
   (TREE_RANGE_CHECK (NODE, OMP_ATOMIC, \