]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
openmp: Support allocate for C/C++ array section reductions
authorJakub Jelinek <jakub@redhat.com>
Fri, 13 Nov 2020 17:57:06 +0000 (18:57 +0100)
committerJakub Jelinek <jakub@redhat.com>
Fri, 13 Nov 2020 17:57:06 +0000 (18:57 +0100)
This adds allocate clause support for array section reductions.
Furthermore, it fixes one bug that would cause inscan reductions with
allocate to be rejected by C, and for now just ignores allocate for
inscan/task reductions, that will need slightly more work.

2020-11-13  Jakub Jelinek  <jakub@redhat.com>

gcc/
* omp-low.c (scan_sharing_clauses): For now remove for reduction
clauses with inscan or task modifiers decl from allocate_map.
(lower_private_allocate): Handle TYPE_P (new_var).
(lower_rec_input_clauses): Handle allocate clause for C/C++ array
reductions.
gcc/c/
* c-typeck.c (c_finish_omp_clauses): Don't clear
OMP_CLAUSE_REDUCTION_INSCAN unless reduction_seen == -2.
libgomp/
* testsuite/libgomp.c-c++-common/allocate-1.c (foo): Add tests
for array reductions.
(main): Adjust foo callers.

gcc/c/c-typeck.c
gcc/omp-low.c
libgomp/testsuite/libgomp.c-c++-common/allocate-1.c

index df1dad468df162c282d2306430cd98a537972dae..26a5f7128d2d53dc824a69d103684e63285a05df 100644 (file)
@@ -15199,7 +15199,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)
+       else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+                && reduction_seen == -2)
          OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
 
        if (remove)
index ed805e2e6d2af97b28eb9c9d82dc2a03775641a9..eec34818f1be107a557b5511c76142ffb5099f82 100644 (file)
@@ -1197,6 +1197,14 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
          if (is_oacc_parallel_or_serial (ctx) || is_oacc_kernels (ctx))
            ctx->local_reduction_clauses
              = tree_cons (NULL, c, ctx->local_reduction_clauses);
+         if ((OMP_CLAUSE_REDUCTION_INSCAN (c)
+              || OMP_CLAUSE_REDUCTION_TASK (c)) && ctx->allocate_map)
+           {
+             tree decl = OMP_CLAUSE_DECL (c);
+             /* For now.  */
+             if (ctx->allocate_map->get (decl))
+               ctx->allocate_map->remove (decl);
+           }
          /* FALLTHRU */
 
        case OMP_CLAUSE_IN_REDUCTION:
@@ -4392,13 +4400,17 @@ lower_private_allocate (tree var, tree new_var, tree &allocator,
   if (allocator)
     return false;
   gcc_assert (allocate_ptr == NULL_TREE);
-  if (ctx->allocate_map && DECL_P (new_var))
+  if (ctx->allocate_map
+      && (DECL_P (new_var) || (TYPE_P (new_var) && size)))
     if (tree *allocatorp = ctx->allocate_map->get (var))
       allocator = *allocatorp;
   if (allocator == NULL_TREE)
     return false;
   if (!is_ref && omp_is_reference (var))
-    return false;
+    {
+      allocator = NULL_TREE;
+      return false;
+    }
 
   if (TREE_CODE (allocator) != INTEGER_CST)
     allocator = build_outer_var_ref (allocator, ctx);
@@ -4410,19 +4422,24 @@ lower_private_allocate (tree var, tree new_var, tree &allocator,
       allocator = var;
     }
 
-  tree ptr_type, align, sz;
-  if (is_ref)
+  tree ptr_type, align, sz = size;
+  if (TYPE_P (new_var))
+    {
+      ptr_type = build_pointer_type (new_var);
+      align = build_int_cst (size_type_node, TYPE_ALIGN_UNIT (new_var));
+    }
+  else if (is_ref)
     {
       ptr_type = build_pointer_type (TREE_TYPE (TREE_TYPE (new_var)));
       align = build_int_cst (size_type_node,
                             TYPE_ALIGN_UNIT (TREE_TYPE (ptr_type)));
-      sz = size;
     }
   else
     {
       ptr_type = build_pointer_type (TREE_TYPE (new_var));
       align = build_int_cst (size_type_node, DECL_ALIGN_UNIT (new_var));
-      sz = fold_convert (size_type_node, DECL_SIZE_UNIT (new_var));
+      if (sz == NULL_TREE)
+       sz = fold_convert (size_type_node, DECL_SIZE_UNIT (new_var));
     }
   if (TREE_CODE (sz) != INTEGER_CST)
     {
@@ -4855,7 +4872,23 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
              tree type = TREE_TYPE (d);
              gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
              tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
+             tree sz = v;
              const char *name = get_name (orig_var);
+             if (pass != 3 && !TREE_CONSTANT (v))
+               {
+                 tree t = maybe_lookup_decl (v, ctx);
+                 if (t)
+                   v = t;
+                 else
+                   v = maybe_lookup_decl_in_outer_ctx (v, ctx);
+                 gimplify_expr (&v, ilist, NULL, is_gimple_val, fb_rvalue);
+                 t = fold_build2_loc (clause_loc, PLUS_EXPR,
+                                      TREE_TYPE (v), v,
+                                      build_int_cst (TREE_TYPE (v), 1));
+                 sz = fold_build2_loc (clause_loc, MULT_EXPR,
+                                       TREE_TYPE (v), t,
+                                       TYPE_SIZE_UNIT (TREE_TYPE (type)));
+               }
              if (pass == 3)
                {
                  tree xv = create_tmp_var (ptr_type_node);
@@ -4913,6 +4946,13 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
                  gimplify_assign (cond, x, ilist);
                  x = xv;
                }
+             else if (lower_private_allocate (var, type, allocator,
+                                              allocate_ptr, ilist, ctx,
+                                              true,
+                                              TREE_CONSTANT (v)
+                                              ? TYPE_SIZE_UNIT (type)
+                                              : sz))
+               x = allocate_ptr;
              else if (TREE_CONSTANT (v))
                {
                  x = create_tmp_var_raw (type, name);
@@ -4924,20 +4964,8 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
                {
                  tree atmp
                    = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
-                 tree t = maybe_lookup_decl (v, ctx);
-                 if (t)
-                   v = t;
-                 else
-                   v = maybe_lookup_decl_in_outer_ctx (v, ctx);
-                 gimplify_expr (&v, ilist, NULL, is_gimple_val, fb_rvalue);
-                 t = fold_build2_loc (clause_loc, PLUS_EXPR,
-                                      TREE_TYPE (v), v,
-                                      build_int_cst (TREE_TYPE (v), 1));
-                 t = fold_build2_loc (clause_loc, MULT_EXPR,
-                                      TREE_TYPE (v), t,
-                                      TYPE_SIZE_UNIT (TREE_TYPE (type)));
                  tree al = size_int (TYPE_ALIGN (TREE_TYPE (type)));
-                 x = build_call_expr_loc (clause_loc, atmp, 2, t, al);
+                 x = build_call_expr_loc (clause_loc, atmp, 2, sz, al);
                }
 
              tree ptype = build_pointer_type (TREE_TYPE (type));
@@ -5199,6 +5227,12 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
                  gimple_seq_add_stmt (dlist, g);
                  gimple_seq_add_stmt (dlist, gimple_build_label (end2));
                }
+             if (allocator)
+               {
+                 tree f = builtin_decl_explicit (BUILT_IN_GOMP_FREE);
+                 g = gimple_build_call (f, 2, allocate_ptr, allocator);
+                 gimple_seq_add_stmt (dlist, g);
+               }
              continue;
            }
          else if (pass == 2)
index 532795f06f146b359cf9aee13df8dc5a3dd53dcb..5dd51b5a2b96504560b9e111af5ec092e8d2137a 100644 (file)
@@ -3,7 +3,7 @@
 #include <stdint.h>
 
 void
-foo (int x, omp_allocator_handle_t h, int fl)
+foo (int x, int *p, int *q, int px, omp_allocator_handle_t h, int fl)
 {
   int y = 0, r = 0, i, i1, l, l2[4], l3, n = 8;
   int i2, j2, n2 = 9, l4;
@@ -11,7 +11,12 @@ foo (int x, omp_allocator_handle_t h, int fl)
   int i4, j4, n4 = 11, l6;
   int i5;
   int v[x], w[x];
+  int r2[4] = { 0, 0, 0, 0 };
   int xo = x;
+  for (i = 0; i < 4; i++)
+    p[i] = 0;
+  for (i = 0; i < 3; i++)
+    q[i] = 0;
   for (i = 0; i < x; i++)
     w[i] = i;
   #pragma omp parallel private (y, v) firstprivate (x) allocate (x, y, v)
@@ -117,6 +122,21 @@ foo (int x, omp_allocator_handle_t h, int fl)
        if ((fl & 2) && (((uintptr_t) &i5) & 63) != 0)
          abort ();
       }
+    #pragma omp for reduction(+:p[2:px], q[:3], r2) allocate(h: p, q, r2)
+    for (i = 0; i < 32; i++)
+      {
+       p[2] += i;
+       p[3] += 2 * i;
+       q[0] += 3 * i;
+       q[2] += 4 * i;
+       r2[0] += 5 * i;
+       r2[3] += 6 * i;
+       /* Can't really rely on alignment of &p[0], the implementation could
+          allocate the whole array or do what GCC does and allocate only part
+          of it.  */
+       if ((fl & 1) && (((uintptr_t) &q[0] | (uintptr_t) &r2[0]) & 63) != 0)
+         abort ();
+      }
   }
   if (r != 64 * 63 / 2 || l != 63 || n != 8 + 16 * 64)
     abort ();
@@ -130,6 +150,10 @@ foo (int x, omp_allocator_handle_t h, int fl)
     abort ();
   if (i5 != 19)
     abort ();
+  if (p[2] != (32 * 31) / 2 || p[3] != 2 * (32 * 31) / 2
+      || q[0] != 3 * (32 * 31) / 2 || q[2] != 4 * (32 * 31) / 2
+      || r2[0] != 5 * (32 * 31) / 2 || r2[3] != 6 * (32 * 31) / 2)
+    abort ();
 }
 
 void
@@ -239,15 +263,16 @@ main ()
        { omp_atk_fallback, omp_atv_null_fb } };
   omp_allocator_handle_t a
     = omp_init_allocator (omp_default_mem_space, 2, traits);
+  int p[4], q[3];
   if (a == omp_null_allocator)
     abort ();
   omp_set_default_allocator (omp_default_mem_alloc);
-  foo (42, omp_null_allocator, 0);
-  foo (42, omp_default_mem_alloc, 0);
-  foo (42, a, 1);
+  foo (42, p, q, 2, omp_null_allocator, 0);
+  foo (42, p, q, 2, omp_default_mem_alloc, 0);
+  foo (42, p, q, 2, a, 1);
   omp_set_default_allocator (a);
-  foo (42, omp_null_allocator, 3);
-  foo (42, omp_default_mem_alloc, 2);
+  foo (42, p, q, 2, omp_null_allocator, 3);
+  foo (42, p, q, 2, omp_default_mem_alloc, 2);
   bar (42, a);
   omp_destroy_allocator (a);
   return 0;