[committed] openmp: Support allocate for C/C++ array section reductions

Jakub Jelinek jakub@redhat.com
Fri Nov 13 17:59:59 GMT 2020


Hi!

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.

Bootstrapped/regtested on x86_64-linux and i686-linux, committed to trunk.

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/omp-low.c.jj	2020-11-12 21:37:53.909422916 +0100
+++ gcc/omp-low.c	2020-11-13 15:55:09.479302108 +0100
@@ -1197,6 +1197,14 @@ scan_sharing_clauses (tree clauses, omp_
 	  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 n
   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 n
       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, g
 	      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, g
 		  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, g
 		{
 		  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, g
 		  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)
--- gcc/c/c-typeck.c.jj	2020-11-10 15:52:44.658924102 +0100
+++ gcc/c/c-typeck.c	2020-11-13 14:33:41.465289312 +0100
@@ -15199,7 +15199,8 @@ c_finish_omp_clauses (tree clauses, enum
 		      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)
--- libgomp/testsuite/libgomp.c-c++-common/allocate-1.c.jj	2020-11-12 21:37:53.913422871 +0100
+++ libgomp/testsuite/libgomp.c-c++-common/allocate-1.c	2020-11-13 16:24:53.037273102 +0100
@@ -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, in
   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, in
 	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, in
     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;

	Jakub



More information about the Gcc-patches mailing list