openmp: Fix handling of allocate clause on taskloop
authorJakub Jelinek <jakub@redhat.com>
Fri, 30 Oct 2020 08:18:36 +0000 (09:18 +0100)
committerJakub Jelinek <jakub@redhat.com>
Fri, 30 Oct 2020 08:18:36 +0000 (09:18 +0100)
This patch fixes gimplification of allocate clause on taskloop - puts
allocate on inner taskloop only if there is allocate clause, because otherwise
the data sharing clauses are only on the task construct in the construct sandwich.

2020-10-30  Jakub Jelinek  <jakub@redhat.com>

* gimplify.c (gimplify_scan_omp_clauses): Force
OMP_CLAUSE_ALLOCATE_ALLOCATOR into a temporary if it is non-NULL and
non-constant.
(gimplify_omp_for): Only put allocate on inner taskloop if lastprivate
for the same variable is going to be put there, and in that case
if the OMP_CLAUSE_ALLOCATE_ALLOCATOR is non-NULL non-constant, make
the allocator firstprivate on task.

* c-c++-common/gomp/allocate-3.c: New test.

gcc/gimplify.c
gcc/testsuite/c-c++-common/gomp/allocate-3.c [new file with mode: 0644]

index f766fee24b9b28b9bde997bc70dde4ccf729eb33..aa3b914f6e5cdee4631ea6c7b8c68778398d49f4 100644 (file)
@@ -9721,6 +9721,13 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
              remove = true;
              break;
            }
+         else if (code == OMP_TASKLOOP
+                  && OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
+                  && (TREE_CODE (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c))
+                      != INTEGER_CST))
+           OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
+             = get_initialized_tmp_var (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c),
+                                        pre_p, NULL, false);
          break;
 
        case OMP_CLAUSE_DEFAULT:
@@ -12120,6 +12127,20 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
       tree *gtask_clauses_ptr = &task_clauses;
       tree outer_for_clauses = NULL_TREE;
       tree *gforo_clauses_ptr = &outer_for_clauses;
+      bitmap lastprivate_uids = NULL;
+      if (omp_find_clause (c, OMP_CLAUSE_ALLOCATE))
+       {
+         c = omp_find_clause (c, OMP_CLAUSE_LASTPRIVATE);
+         if (c)
+           {
+             lastprivate_uids = BITMAP_ALLOC (NULL);
+             for (; c; c = omp_find_clause (OMP_CLAUSE_CHAIN (c),
+                                            OMP_CLAUSE_LASTPRIVATE))
+               bitmap_set_bit (lastprivate_uids,
+                               DECL_UID (OMP_CLAUSE_DECL (c)));
+           }
+         c = *gfor_clauses_ptr;
+       }
       for (; c; c = OMP_CLAUSE_CHAIN (c))
        switch (OMP_CLAUSE_CODE (c))
          {
@@ -12207,12 +12228,35 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
            gtask_clauses_ptr
              = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr);
            break;
-         /* Allocate clause we duplicate on task and inner taskloop.  */
+         /* Allocate clause we duplicate on task and inner taskloop
+            if the decl is lastprivate, otherwise just put on task.  */
          case OMP_CLAUSE_ALLOCATE:
-           *gfor_clauses_ptr = c;
-           gfor_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
-           *gtask_clauses_ptr = copy_node (c);
-           gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr);
+           if (lastprivate_uids
+               && bitmap_bit_p (lastprivate_uids,
+                                DECL_UID (OMP_CLAUSE_DECL (c))))
+             {
+               if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
+                   && DECL_P (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)))
+                 {
+                   /* Additionally, put firstprivate clause on task
+                      for the allocator if it is not constant.  */
+                   *gtask_clauses_ptr
+                     = build_omp_clause (OMP_CLAUSE_LOCATION (c),
+                                         OMP_CLAUSE_FIRSTPRIVATE);
+                   OMP_CLAUSE_DECL (*gtask_clauses_ptr)
+                     = OMP_CLAUSE_ALLOCATE_ALLOCATOR (c);
+                   gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr);
+                 }
+               *gfor_clauses_ptr = c;
+               gfor_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
+               *gtask_clauses_ptr = copy_node (c);
+               gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr);
+             }
+           else
+             {
+               *gtask_clauses_ptr = c;
+               gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
+             }
            break;
          default:
            gcc_unreachable ();
@@ -12220,6 +12264,7 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
       *gfor_clauses_ptr = NULL_TREE;
       *gtask_clauses_ptr = NULL_TREE;
       *gforo_clauses_ptr = NULL_TREE;
+      BITMAP_FREE (lastprivate_uids);
       g = gimple_build_bind (NULL_TREE, gfor, NULL_TREE);
       g = gimple_build_omp_task (g, task_clauses, NULL_TREE, NULL_TREE,
                                 NULL_TREE, NULL_TREE, NULL_TREE);
diff --git a/gcc/testsuite/c-c++-common/gomp/allocate-3.c b/gcc/testsuite/c-c++-common/gomp/allocate-3.c
new file mode 100644 (file)
index 0000000..e61cc1e
--- /dev/null
@@ -0,0 +1,38 @@
+typedef enum omp_allocator_handle_t
+#if __cplusplus >= 201103L
+: __UINTPTR_TYPE__
+#endif
+{
+  omp_null_allocator = 0,
+  omp_default_mem_alloc = 1,
+  omp_large_cap_mem_alloc = 2,
+  omp_const_mem_alloc = 3,
+  omp_high_bw_mem_alloc = 4,
+  omp_low_lat_mem_alloc = 5,
+  omp_cgroup_mem_alloc = 6,
+  omp_pteam_mem_alloc = 7,
+  omp_thread_mem_alloc = 8,
+  __omp_allocator_handle_t_max__ = __UINTPTR_MAX__
+} omp_allocator_handle_t;
+
+omp_allocator_handle_t baz (int);
+
+int
+foo (omp_allocator_handle_t h1, omp_allocator_handle_t h2, int y)
+{
+  int x;
+  #pragma omp taskloop default(none) lastprivate (x) allocate (h1:x) firstprivate(y) allocate (h2:y)
+  for (int i = 0; i < 64; i++)
+    x = y + i;
+  return x;
+}
+
+int
+bar (int y)
+{
+  int x;
+  #pragma omp taskloop default(none) lastprivate (x) allocate (baz (0):x) allocate (baz (1):y) firstprivate(y)
+  for (int i = 0; i < 64; i++)
+    x = y + i;
+  return x;
+}