]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
openmp: Ensure copy ctor for composite distribute parallel for class iterators is...
authorJakub Jelinek <jakub@redhat.com>
Tue, 26 May 2020 07:35:21 +0000 (09:35 +0200)
committerJakub Jelinek <jakub@redhat.com>
Sun, 14 Jun 2020 10:06:22 +0000 (12:06 +0200)
During gimplification omp_finish_clause langhook is called in several places
to add the language specific info to the clause like what default/copy ctors,
dtors and assignment operators should be used.

Unfortunately, if it refers to some not yet instantiated method, during
gimplification it is too late and the methods will not be instantiated
anymore.  For other cases, the genericizer has code to detect those and
instantiate whatever is needed, this change adds the same for
distribute parallel for class iterators where we under the hood need
a copy constructor for the iterator to implement it.

2020-05-26  Jakub Jelinek  <jakub@redhat.com>

PR c++/95197
* gimplify.c (find_combined_omp_for): Move to omp-general.c.
* omp-general.h (find_combined_omp_for): Declare.
* omp-general.c: Include tree-iterator.h.
(find_combined_omp_for): New function, moved from gimplify.c.

* cp-gimplify.c: Include omp-general.h.
(cp_genericize_r) <case OMP_DISTRIBUTE>: For class iteration
variables in composite distribute parallel for, instantiate copy
ctor of their types.

(cherry picked from commit f1f862aec2c3b93dbd6adfc35b0e1b6034e59c21)

gcc/cp/cp-gimplify.c
gcc/gimplify.c
gcc/omp-general.c
gcc/omp-general.h

index 0cf5bbb60b666d22e3f8361f1ffd9895b736ba67..11b836f7bb976e13be7f57e9d6cbae4e264d46d4 100644 (file)
@@ -40,6 +40,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "output.h"
 #include "file-prefix-map.h"
 #include "cgraph.h"
+#include "omp-general.h"
 
 /* Forward declarations.  */
 
@@ -1645,9 +1646,70 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
       *stmt_p = genericize_spaceship (*stmt_p);
       break;
 
+    case OMP_DISTRIBUTE:
+      /* Need to explicitly instantiate copy ctors on class iterators of
+        composite distribute parallel for.  */
+      if (OMP_FOR_INIT (*stmt_p) == NULL_TREE)
+       {
+         tree *data[4] = { NULL, NULL, NULL, NULL };
+         tree inner = walk_tree (&OMP_FOR_BODY (*stmt_p),
+                                 find_combined_omp_for, data, NULL);
+         if (inner != NULL_TREE
+             && TREE_CODE (inner) == OMP_FOR)
+           {
+             for (int i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (inner)); i++)
+               if (OMP_FOR_ORIG_DECLS (inner)
+                   && TREE_CODE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner),
+                                 i)) == TREE_LIST
+                   && TREE_PURPOSE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner),
+                                    i)))
+                 {
+                   tree orig = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner), i);
+                   /* Class iterators aren't allowed on OMP_SIMD, so the only
+                      case we need to solve is distribute parallel for.  */
+                   gcc_assert (TREE_CODE (inner) == OMP_FOR
+                               && data[1]);
+                   tree orig_decl = TREE_PURPOSE (orig);
+                   tree c, cl = NULL_TREE;
+                   for (c = OMP_FOR_CLAUSES (inner);
+                        c; c = OMP_CLAUSE_CHAIN (c))
+                     if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
+                          || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
+                         && OMP_CLAUSE_DECL (c) == orig_decl)
+                       {
+                         cl = c;
+                         break;
+                       }
+                   if (cl == NULL_TREE)
+                     {
+                       for (c = OMP_PARALLEL_CLAUSES (*data[1]);
+                            c; c = OMP_CLAUSE_CHAIN (c))
+                         if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
+                             && OMP_CLAUSE_DECL (c) == orig_decl)
+                           {
+                             cl = c;
+                             break;
+                           }
+                     }
+                   if (cl)
+                     {
+                       orig_decl = require_complete_type (orig_decl);
+                       tree inner_type = TREE_TYPE (orig_decl);
+                       if (orig_decl == error_mark_node)
+                         continue;
+                       if (TYPE_REF_P (TREE_TYPE (orig_decl)))
+                         inner_type = TREE_TYPE (inner_type);
+
+                       while (TREE_CODE (inner_type) == ARRAY_TYPE)
+                         inner_type = TREE_TYPE (inner_type);
+                       get_copy_ctor (inner_type, tf_warning_or_error);
+                     }
+               }
+           }
+       }
+      /* FALLTHRU */
     case OMP_FOR:
     case OMP_SIMD:
-    case OMP_DISTRIBUTE:
     case OMP_LOOP:
     case OACC_LOOP:
       genericize_omp_for_stmt (stmt_p, walk_subtrees, data);
index 4b3306cfc258e076dd72273b5d23c22adab3d795..ff40cf1376966f162bc2946d093fc39adeba7e8d 100644 (file)
@@ -10987,62 +10987,6 @@ gimplify_omp_task (tree *expr_p, gimple_seq *pre_p)
   *expr_p = NULL_TREE;
 }
 
-/* Helper function of gimplify_omp_for, find OMP_FOR resp. OMP_SIMD
-   with non-NULL OMP_FOR_INIT.  Also, fill in pdata array,
-   pdata[0] non-NULL if there is anything non-trivial in between, pdata[1]
-   is address of OMP_PARALLEL in between if any, pdata[2] is address of
-   OMP_FOR in between if any and pdata[3] is address of the inner
-   OMP_FOR/OMP_SIMD.  */
-
-static tree
-find_combined_omp_for (tree *tp, int *walk_subtrees, void *data)
-{
-  tree **pdata = (tree **) data;
-  *walk_subtrees = 0;
-  switch (TREE_CODE (*tp))
-    {
-    case OMP_FOR:
-      if (OMP_FOR_INIT (*tp) != NULL_TREE)
-       {
-         pdata[3] = tp;
-         return *tp;
-       }
-      pdata[2] = tp;
-      *walk_subtrees = 1;
-      break;
-    case OMP_SIMD:
-      if (OMP_FOR_INIT (*tp) != NULL_TREE)
-       {
-         pdata[3] = tp;
-         return *tp;
-       }
-      break;
-    case BIND_EXPR:
-      if (BIND_EXPR_VARS (*tp)
-         || (BIND_EXPR_BLOCK (*tp)
-             && BLOCK_VARS (BIND_EXPR_BLOCK (*tp))))
-       pdata[0] = tp;
-      *walk_subtrees = 1;
-      break;
-    case STATEMENT_LIST:
-      if (!tsi_one_before_end_p (tsi_start (*tp)))
-       pdata[0] = tp;
-      *walk_subtrees = 1;
-      break;
-    case TRY_FINALLY_EXPR:
-      pdata[0] = tp;
-      *walk_subtrees = 1;
-      break;
-    case OMP_PARALLEL:
-      pdata[1] = tp;
-      *walk_subtrees = 1;
-      break;
-    default:
-      break;
-    }
-  return NULL_TREE;
-}
-
 /* Gimplify the gross structure of an OMP_FOR statement.  */
 
 static enum gimplify_status
index 49023f42c473ae52ef0827d856f98537d99ed101..aed0e4efd60b7ef8f1fec37e9d21ea368f4e4f94 100644 (file)
@@ -42,6 +42,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "hsa-common.h"
 #include "tree-pass.h"
 #include "omp-device-properties.h"
+#include "tree-iterator.h"
 
 enum omp_requires omp_requires_mask;
 
@@ -504,6 +505,61 @@ omp_build_barrier (tree lhs)
   return g;
 }
 
+/* Find OMP_FOR resp. OMP_SIMD with non-NULL OMP_FOR_INIT.  Also, fill in pdata
+   array, pdata[0] non-NULL if there is anything non-trivial in between,
+   pdata[1] is address of OMP_PARALLEL in between if any, pdata[2] is address
+   of OMP_FOR in between if any and pdata[3] is address of the inner
+   OMP_FOR/OMP_SIMD.  */
+
+tree
+find_combined_omp_for (tree *tp, int *walk_subtrees, void *data)
+{
+  tree **pdata = (tree **) data;
+  *walk_subtrees = 0;
+  switch (TREE_CODE (*tp))
+    {
+    case OMP_FOR:
+      if (OMP_FOR_INIT (*tp) != NULL_TREE)
+       {
+         pdata[3] = tp;
+         return *tp;
+       }
+      pdata[2] = tp;
+      *walk_subtrees = 1;
+      break;
+    case OMP_SIMD:
+      if (OMP_FOR_INIT (*tp) != NULL_TREE)
+       {
+         pdata[3] = tp;
+         return *tp;
+       }
+      break;
+    case BIND_EXPR:
+      if (BIND_EXPR_VARS (*tp)
+         || (BIND_EXPR_BLOCK (*tp)
+             && BLOCK_VARS (BIND_EXPR_BLOCK (*tp))))
+       pdata[0] = tp;
+      *walk_subtrees = 1;
+      break;
+    case STATEMENT_LIST:
+      if (!tsi_one_before_end_p (tsi_start (*tp)))
+       pdata[0] = tp;
+      *walk_subtrees = 1;
+      break;
+    case TRY_FINALLY_EXPR:
+      pdata[0] = tp;
+      *walk_subtrees = 1;
+      break;
+    case OMP_PARALLEL:
+      pdata[1] = tp;
+      *walk_subtrees = 1;
+      break;
+    default:
+      break;
+    }
+  return NULL_TREE;
+}
+
 /* Return maximum possible vectorization factor for the target.  */
 
 poly_uint64
index f4cc302e5b96b2b679b4edc148c5fec7d7343b0f..ad28b2b7970f13d789b9baed3d072b7207cf9310 100644 (file)
@@ -82,6 +82,7 @@ extern tree omp_get_for_step_from_incr (location_t loc, tree incr);
 extern void omp_extract_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
                                  struct omp_for_data_loop *loops);
 extern gimple *omp_build_barrier (tree lhs);
+extern tree find_combined_omp_for (tree *, int *, void *);
 extern poly_uint64 omp_max_vf (void);
 extern int omp_max_simt_vf (void);
 extern int omp_constructor_traits_to_codes (tree, enum tree_code *);