[PATCH 3/5] openmp: Outline lower_omp_target_grid_desc from lower_omp_target

Paul-Antoine Arras <[email protected]> Wed, 5 Aug 2026 22:23:41 +0200
Newsgroups gmane.comp.gcc.patches
Message-ID <[email protected]>
Move the noncontiguous-array descriptor construction for
GOMP_MAP_TO_GRID/GOMP_MAP_FROM_GRID clauses out of lower_omp_target's
clause-processing loop into its own static function. Pure code motion,
no behavior change; the generalization to array-shaping casts,
array-of-pointers sections, and multi-segment descriptors follows in a
separate change.

gcc/ChangeLog:

	* omp-low.cc (lower_omp_target_grid_desc): New, extracted from
	lower_omp_target.
	(lower_omp_target): Call it instead of building the descriptor
	inline.
---
 gcc/omp-low.cc | 656 +++++++++++++++++++++++++------------------------
 1 file changed, 335 insertions(+), 321 deletions(-)

diff --git a/gcc/omp-low.cc b/gcc/omp-low.cc
index 837a0493c91..45f6c701f48 100644
--- a/gcc/omp-low.cc
+++ b/gcc/omp-low.cc
@@ -13723,6 +13723,340 @@ convert_from_firstprivate_int (tree var, tree orig_type, bool is_ref,
   gimplify_assign (tmp, var, gs);
 
   return fold_build1 (VIEW_CONVERT_EXPR, type, tmp);
+
+/* Build the noncontiguous-array descriptor for the
+   GOMP_MAP_TO_GRID/GOMP_MAP_FROM_GRID clause C (whose GOMP_MAP_TO_PSET
+   sibling clause holds the descriptor decl and the GOMP_MAP_GRID_DIM/
+   GOMP_MAP_GRID_STRIDE clauses that follow describe each dimension).  Any
+   gimplification needed to initialize the descriptor is appended to
+   *ILIST_P.  */
+
+static void
+lower_omp_target_grid_desc (tree c, gimple_seq *ilist_p)
+{
+  tree decl = OMP_CLAUSE_DECL (c);
+  tree dn = OMP_CLAUSE_CHAIN (c);
+  gcc_assert (OMP_CLAUSE_CODE (dn) == OMP_CLAUSE_MAP
+	      && OMP_CLAUSE_MAP_KIND (dn) == GOMP_MAP_TO_PSET);
+  tree desc = OMP_CLAUSE_DECL (dn);
+
+  tree oc, elsize = OMP_CLAUSE_SIZE (c);
+  tree type = TREE_TYPE (decl);
+  int i, dims = 0;
+  tree nc;
+  auto_vec<tree> tdims;
+  bool pointer_based = false, handled_pointer_section = false;
+  tree arrsize = size_one_node;
+
+  /* Allow a single (maybe strided) array section if we have a
+     pointer base.  */
+  if (TREE_CODE (decl) == INDIRECT_REF
+      && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
+	  == POINTER_TYPE))
+    {
+      pointer_based = true;
+      dims = 1;
+    }
+  else
+    /* NOTE: Don't treat (e.g. Fortran, fixed-length) strings as
+       array types here; array section syntax isn't applicable to
+       strings.  */
+    for (tree itype = type;
+	 TREE_CODE (itype) == ARRAY_TYPE
+	 && !TYPE_STRING_FLAG (itype);
+	 itype = TREE_TYPE (itype))
+      {
+	tdims.safe_push (itype);
+	dims++;
+      }
+
+  unsigned tdim = 0;
+
+  vec<constructor_elt, va_gc> *vdim;
+  vec<constructor_elt, va_gc> *vindex;
+  vec<constructor_elt, va_gc> *vlen;
+  vec<constructor_elt, va_gc> *vstride;
+  vec_alloc (vdim, dims);
+  vec_alloc (vindex, dims);
+  vec_alloc (vlen, dims);
+  vec_alloc (vstride, dims);
+
+  tree size_arr_type
+    = build_array_type_nelts (size_type_node, dims);
+
+  tree dim_tmp = create_tmp_var (size_arr_type, ".omp_dim");
+  DECL_NAMELESS (dim_tmp) = 1;
+  TREE_ADDRESSABLE (dim_tmp) = 1;
+  TREE_STATIC (dim_tmp) = 1;
+  tree index_tmp = create_tmp_var (size_arr_type, ".omp_index");
+  DECL_NAMELESS (index_tmp) = 1;
+  TREE_ADDRESSABLE (index_tmp) = 1;
+  TREE_STATIC (index_tmp) = 1;
+  tree len_tmp = create_tmp_var (size_arr_type, ".omp_len");
+  DECL_NAMELESS (len_tmp) = 1;
+  TREE_ADDRESSABLE (len_tmp) = 1;
+  TREE_STATIC (len_tmp) = 1;
+  tree stride_tmp = create_tmp_var (size_arr_type, ".omp_stride");
+  DECL_NAMELESS (stride_tmp) = 1;
+  TREE_ADDRESSABLE (stride_tmp) = 1;
+  TREE_STATIC (stride_tmp) = 1;
+
+  oc = c;
+  c = dn;
+
+  tree span = NULL_TREE;
+
+  for (i = 0; i < dims; i++)
+    {
+      nc = OMP_CLAUSE_CHAIN (c);
+      tree dim = NULL_TREE, index = NULL_TREE, len = NULL_TREE,
+	   stride = size_one_node;
+
+      if (nc
+	  && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
+	  && OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_GRID_DIM)
+	{
+	  index = OMP_CLAUSE_DECL (nc);
+	  len = OMP_CLAUSE_SIZE (nc);
+
+	  index = fold_convert (sizetype, index);
+	  len = fold_convert (sizetype, len);
+
+	  tree nc2 = OMP_CLAUSE_CHAIN (nc);
+	  if (nc2
+	      && OMP_CLAUSE_CODE (nc2) == OMP_CLAUSE_MAP
+	      && (OMP_CLAUSE_MAP_KIND (nc2)
+		  == GOMP_MAP_GRID_STRIDE))
+	    {
+	      stride = OMP_CLAUSE_DECL (nc2);
+	      stride = fold_convert (sizetype, stride);
+	      if (OMP_CLAUSE_SIZE (nc2))
+		{
+		  /* If the element size is not the same as the
+		     distance between two adjacent array
+		     elements (in the innermost dimension),
+		     retrieve the latter value ("span") from the
+		     size field of the stride.  We only expect to
+		     see one such field per array.  */
+		  gcc_assert (!span);
+		  span = OMP_CLAUSE_SIZE (nc2);
+		  span = fold_convert (sizetype, span);
+		}
+	      nc = nc2;
+	    }
+
+	  if (tdim < tdims.length ())
+	    {
+	      /* We have an array shape -- use that to find the
+		 total size of the data on the target to look up
+		 in libgomp.  */
+	      tree dtype = TYPE_DOMAIN (tdims[tdim]);
+	      tree minval = TYPE_MIN_VALUE (dtype);
+	      tree maxval = TYPE_MAX_VALUE (dtype);
+	      minval = fold_convert (sizetype, minval);
+	      maxval = fold_convert (sizetype, maxval);
+	      dim = size_binop (MINUS_EXPR, maxval, minval);
+	      dim = size_binop (PLUS_EXPR, dim,
+				size_one_node);
+	      arrsize = size_binop (MULT_EXPR, arrsize, dim);
+	    }
+	  else if (pointer_based && !handled_pointer_section)
+	    {
+	      /* Use the selected array section to determine the
+		 size of the array.  */
+	      tree tmp = size_binop (MULT_EXPR, len, stride);
+	      tmp = size_binop (MINUS_EXPR, tmp, stride);
+	      tmp = size_binop (PLUS_EXPR, tmp, size_one_node);
+	      dim = size_binop (PLUS_EXPR, index, tmp);
+	      arrsize = size_binop (MULT_EXPR, arrsize, dim);
+	      handled_pointer_section = true;
+	    }
+	  else
+	    {
+	      if (pointer_based)
+		error_at (OMP_CLAUSE_LOCATION (c),
+			  "too many array section specifiers "
+			  "for pointer-based array");
+	      else
+		error_at (OMP_CLAUSE_LOCATION (c),
+			  "too many array section specifiers "
+			  "for array");
+	      dim = index = len = stride = error_mark_node;
+	    }
+	  tdim++;
+
+	  c = nc;
+	}
+      else
+	{
+	  /* We have more array dimensions than array section
+	     specifiers.  Copy the whole span.  */
+	  tree dtype = TYPE_DOMAIN (tdims[tdim]);
+	  tree minval = TYPE_MIN_VALUE (dtype);
+	  tree maxval = TYPE_MAX_VALUE (dtype);
+	  minval = fold_convert (sizetype, minval);
+	  maxval = fold_convert (sizetype, maxval);
+	  dim = size_binop (MINUS_EXPR, maxval, minval);
+	  dim = size_binop (PLUS_EXPR, dim, size_one_node);
+	  len = dim;
+	  index = minval;
+	  nc = c;
+	}
+
+      if (TREE_CODE (dim) != INTEGER_CST)
+	TREE_STATIC (dim_tmp) = 0;
+
+      if (TREE_CODE (index) != INTEGER_CST)
+	TREE_STATIC (index_tmp) = 0;
+
+      if (TREE_CODE (len) != INTEGER_CST)
+	TREE_STATIC (len_tmp) = 0;
+
+      if (TREE_CODE (stride) != INTEGER_CST)
+	TREE_STATIC (stride_tmp) = 0;
+
+      tree cidx = size_int (i);
+      CONSTRUCTOR_APPEND_ELT (vdim, cidx, dim);
+      CONSTRUCTOR_APPEND_ELT (vindex, cidx, index);
+      CONSTRUCTOR_APPEND_ELT (vlen, cidx, len);
+      CONSTRUCTOR_APPEND_ELT (vstride, cidx, stride);
+    }
+
+  tree bias = size_zero_node;
+  tree volume = size_one_node;
+  tree enclosure = size_one_node;
+  for (i = dims - 1; i >= 0; i--)
+    {
+      tree dim = (*vdim)[i].value;
+      tree index = (*vindex)[i].value;
+      tree stride = (*vstride)[i].value;
+      tree len = (*vlen)[i].value;
+
+      /* For the bias we want, e.g.:
+
+	     index[0] * stride[0] * dim[1] * dim[2]
+	   + index[1] * stride[1] * dim[2]
+	   + index[2] * stride[2]
+
+	 All multiplied by "span" (or "elsize").  */
+
+      tree index_stride = size_binop (MULT_EXPR, index, stride);
+      bias = size_binop (PLUS_EXPR, bias,
+			 size_binop (MULT_EXPR, volume,
+				     index_stride));
+      volume = size_binop (MULT_EXPR, volume, dim);
+
+      if (i == 0)
+	{
+	  tree elems_covered = size_binop (MINUS_EXPR, len,
+					   size_one_node);
+	  elems_covered = size_binop (MULT_EXPR, elems_covered,
+				      stride);
+	  elems_covered = size_binop (PLUS_EXPR, elems_covered,
+				      size_one_node);
+	  enclosure = size_binop (MULT_EXPR, enclosure,
+				  elems_covered);
+	}
+      else
+	enclosure = volume;
+    }
+
+  /* If we don't have a separate span size, use the element size
+     instead.  */
+  if (!span)
+    span = fold_convert (sizetype, elsize);
+
+  /* The size of a volume enclosing the elements to be
+     transferred.  */
+  OMP_CLAUSE_SIZE (oc) = size_binop (MULT_EXPR, enclosure, span);
+  /* And the bias of the first element we will update.  */
+  OMP_CLAUSE_SIZE (dn) = size_binop (MULT_EXPR, bias, span);
+
+  tree cdim = build_constructor (size_arr_type, vdim);
+  tree cindex = build_constructor (size_arr_type, vindex);
+  tree clen = build_constructor (size_arr_type, vlen);
+  tree cstride = build_constructor (size_arr_type, vstride);
+
+  if (TREE_STATIC (dim_tmp))
+    DECL_INITIAL (dim_tmp) = cdim;
+  else
+    gimplify_assign (dim_tmp, cdim, ilist_p);
+
+  if (TREE_STATIC (index_tmp))
+    DECL_INITIAL (index_tmp) = cindex;
+  else
+    gimplify_assign (index_tmp, cindex, ilist_p);
+
+  if (TREE_STATIC (len_tmp))
+    DECL_INITIAL (len_tmp) = clen;
+  else
+    gimplify_assign (len_tmp, clen, ilist_p);
+
+  if (TREE_STATIC (stride_tmp))
+    DECL_INITIAL (stride_tmp) = cstride;
+  else
+    gimplify_assign (stride_tmp, cstride, ilist_p);
+
+  tree desc_type = TREE_TYPE (desc);
+
+  tree ndims_field = TYPE_FIELDS (desc_type);
+  tree elemsize_field = DECL_CHAIN (ndims_field);
+  tree span_field = DECL_CHAIN (elemsize_field);
+  tree dim_field = DECL_CHAIN (span_field);
+  tree index_field = DECL_CHAIN (dim_field);
+  tree len_field = DECL_CHAIN (index_field);
+  tree stride_field = DECL_CHAIN (len_field);
+
+  vec<constructor_elt, va_gc> *v;
+  vec_alloc (v, 7);
+
+  bool all_static = (TREE_STATIC (dim_tmp)
+		     && TREE_STATIC (index_tmp)
+		     && TREE_STATIC (len_tmp)
+		     && TREE_STATIC (stride_tmp));
+
+  dim_tmp = build4 (ARRAY_REF, sizetype, dim_tmp, size_zero_node,
+		    NULL_TREE, NULL_TREE);
+  dim_tmp = build_fold_addr_expr (dim_tmp);
+
+  /* TODO: we could skip all-zeros index.  */
+  index_tmp = build4 (ARRAY_REF, sizetype, index_tmp,
+		      size_zero_node, NULL_TREE, NULL_TREE);
+  index_tmp = build_fold_addr_expr (index_tmp);
+
+  len_tmp = build4 (ARRAY_REF, sizetype, len_tmp, size_zero_node,
+		    NULL_TREE, NULL_TREE);
+  len_tmp = build_fold_addr_expr (len_tmp);
+
+  /* TODO: we could skip all-ones stride.  */
+  stride_tmp = build4 (ARRAY_REF, sizetype, stride_tmp,
+		       size_zero_node, NULL_TREE, NULL_TREE);
+  stride_tmp = build_fold_addr_expr (stride_tmp);
+
+  elsize = fold_convert (sizetype, elsize);
+  tree ndims = size_int (dims);
+
+  CONSTRUCTOR_APPEND_ELT (v, ndims_field, ndims);
+  CONSTRUCTOR_APPEND_ELT (v, elemsize_field, elsize);
+  CONSTRUCTOR_APPEND_ELT (v, span_field, span);
+  CONSTRUCTOR_APPEND_ELT (v, dim_field, dim_tmp);
+  CONSTRUCTOR_APPEND_ELT (v, index_field, index_tmp);
+  CONSTRUCTOR_APPEND_ELT (v, len_field, len_tmp);
+  CONSTRUCTOR_APPEND_ELT (v, stride_field, stride_tmp);
+
+  tree desc_ctor = build_constructor (desc_type, v);
+
+  if (all_static)
+    {
+      TREE_STATIC (desc) = 1;
+      DECL_INITIAL (desc) = desc_ctor;
+    }
+  else
+    gimplify_assign (desc, desc_ctor, ilist_p);
+
+  OMP_CLAUSE_CHAIN (dn) = OMP_CLAUSE_CHAIN (nc);
+}
+
 }
 
 /* Lower the GIMPLE_OMP_TARGET in the current statement
@@ -14427,327 +14761,7 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
 		&& (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_TO_GRID
 		    || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FROM_GRID))
 	      {
-		tree decl = OMP_CLAUSE_DECL (c);
-		tree dn = OMP_CLAUSE_CHAIN (c);
-		gcc_assert (OMP_CLAUSE_CODE (dn) == OMP_CLAUSE_MAP
-			    && OMP_CLAUSE_MAP_KIND (dn) == GOMP_MAP_TO_PSET);
-		tree desc = OMP_CLAUSE_DECL (dn);
-
-		tree oc, elsize = OMP_CLAUSE_SIZE (c);
-		tree type = TREE_TYPE (decl);
-		int i, dims = 0;
-		auto_vec<tree> tdims;
-		bool pointer_based = false, handled_pointer_section = false;
-		tree arrsize = size_one_node;
-
-		/* Allow a single (maybe strided) array section if we have a
-		   pointer base.  */
-		if (TREE_CODE (decl) == INDIRECT_REF
-		    && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
-			== POINTER_TYPE))
-		  {
-		    pointer_based = true;
-		    dims = 1;
-		  }
-		else
-		  /* NOTE: Don't treat (e.g. Fortran, fixed-length) strings as
-		     array types here; array section syntax isn't applicable to
-		     strings.  */
-		  for (tree itype = type;
-		       TREE_CODE (itype) == ARRAY_TYPE
-		       && !TYPE_STRING_FLAG (itype);
-		       itype = TREE_TYPE (itype))
-		    {
-		      tdims.safe_push (itype);
-		      dims++;
-		    }
-
-		unsigned tdim = 0;
-
-		vec<constructor_elt, va_gc> *vdim;
-		vec<constructor_elt, va_gc> *vindex;
-		vec<constructor_elt, va_gc> *vlen;
-		vec<constructor_elt, va_gc> *vstride;
-		vec_alloc (vdim, dims);
-		vec_alloc (vindex, dims);
-		vec_alloc (vlen, dims);
-		vec_alloc (vstride, dims);
-
-		tree size_arr_type
-		  = build_array_type_nelts (size_type_node, dims);
-
-		tree dim_tmp = create_tmp_var (size_arr_type, ".omp_dim");
-		DECL_NAMELESS (dim_tmp) = 1;
-		TREE_ADDRESSABLE (dim_tmp) = 1;
-		TREE_STATIC (dim_tmp) = 1;
-		tree index_tmp = create_tmp_var (size_arr_type, ".omp_index");
-		DECL_NAMELESS (index_tmp) = 1;
-		TREE_ADDRESSABLE (index_tmp) = 1;
-		TREE_STATIC (index_tmp) = 1;
-		tree len_tmp = create_tmp_var (size_arr_type, ".omp_len");
-		DECL_NAMELESS (len_tmp) = 1;
-		TREE_ADDRESSABLE (len_tmp) = 1;
-		TREE_STATIC (len_tmp) = 1;
-		tree stride_tmp = create_tmp_var (size_arr_type, ".omp_stride");
-		DECL_NAMELESS (stride_tmp) = 1;
-		TREE_ADDRESSABLE (stride_tmp) = 1;
-		TREE_STATIC (stride_tmp) = 1;
-
-		oc = c;
-		c = dn;
-
-		tree span = NULL_TREE;
-
-		for (i = 0; i < dims; i++)
-		  {
-		    nc = OMP_CLAUSE_CHAIN (c);
-		    tree dim = NULL_TREE, index = NULL_TREE, len = NULL_TREE,
-			 stride = size_one_node;
-
-		    if (nc
-			&& OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
-			&& OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_GRID_DIM)
-		      {
-			index = OMP_CLAUSE_DECL (nc);
-			len = OMP_CLAUSE_SIZE (nc);
-
-			index = fold_convert (sizetype, index);
-			len = fold_convert (sizetype, len);
-
-			tree nc2 = OMP_CLAUSE_CHAIN (nc);
-			if (nc2
-			    && OMP_CLAUSE_CODE (nc2) == OMP_CLAUSE_MAP
-			    && (OMP_CLAUSE_MAP_KIND (nc2)
-				== GOMP_MAP_GRID_STRIDE))
-			  {
-			    stride = OMP_CLAUSE_DECL (nc2);
-			    stride = fold_convert (sizetype, stride);
-			    if (OMP_CLAUSE_SIZE (nc2))
-			      {
-				/* If the element size is not the same as the
-				   distance between two adjacent array
-				   elements (in the innermost dimension),
-				   retrieve the latter value ("span") from the
-				   size field of the stride.  We only expect to
-				   see one such field per array.  */
-				gcc_assert (!span);
-				span = OMP_CLAUSE_SIZE (nc2);
-				span = fold_convert (sizetype, span);
-			      }
-			    nc = nc2;
-			  }
-
-			if (tdim < tdims.length ())
-			  {
-			    /* We have an array shape -- use that to find the
-			       total size of the data on the target to look up
-			       in libgomp.  */
-			    tree dtype = TYPE_DOMAIN (tdims[tdim]);
-			    tree minval = TYPE_MIN_VALUE (dtype);
-			    tree maxval = TYPE_MAX_VALUE (dtype);
-			    minval = fold_convert (sizetype, minval);
-			    maxval = fold_convert (sizetype, maxval);
-			    dim = size_binop (MINUS_EXPR, maxval, minval);
-			    dim = size_binop (PLUS_EXPR, dim,
-					      size_one_node);
-			    arrsize = size_binop (MULT_EXPR, arrsize, dim);
-			  }
-			else if (pointer_based && !handled_pointer_section)
-			  {
-			    /* Use the selected array section to determine the
-			       size of the array.  */
-			    tree tmp = size_binop (MULT_EXPR, len, stride);
-			    tmp = size_binop (MINUS_EXPR, tmp, stride);
-			    tmp = size_binop (PLUS_EXPR, tmp, size_one_node);
-			    dim = size_binop (PLUS_EXPR, index, tmp);
-			    arrsize = size_binop (MULT_EXPR, arrsize, dim);
-			    handled_pointer_section = true;
-			  }
-			else
-			  {
-			    if (pointer_based)
-			      error_at (OMP_CLAUSE_LOCATION (c),
-					"too many array section specifiers "
-					"for pointer-based array");
-			    else
-			      error_at (OMP_CLAUSE_LOCATION (c),
-					"too many array section specifiers "
-					"for array");
-			    dim = index = len = stride = error_mark_node;
-			  }
-			tdim++;
-
-			c = nc;
-		      }
-		    else
-		      {
-			/* We have more array dimensions than array section
-			   specifiers.  Copy the whole span.  */
-			tree dtype = TYPE_DOMAIN (tdims[tdim]);
-			tree minval = TYPE_MIN_VALUE (dtype);
-			tree maxval = TYPE_MAX_VALUE (dtype);
-			minval = fold_convert (sizetype, minval);
-			maxval = fold_convert (sizetype, maxval);
-			dim = size_binop (MINUS_EXPR, maxval, minval);
-			dim = size_binop (PLUS_EXPR, dim, size_one_node);
-			len = dim;
-			index = minval;
-			nc = c;
-		      }
-
-		    if (TREE_CODE (dim) != INTEGER_CST)
-		      TREE_STATIC (dim_tmp) = 0;
-
-		    if (TREE_CODE (index) != INTEGER_CST)
-		      TREE_STATIC (index_tmp) = 0;
-
-		    if (TREE_CODE (len) != INTEGER_CST)
-		      TREE_STATIC (len_tmp) = 0;
-
-		    if (TREE_CODE (stride) != INTEGER_CST)
-		      TREE_STATIC (stride_tmp) = 0;
-
-		    tree cidx = size_int (i);
-		    CONSTRUCTOR_APPEND_ELT (vdim, cidx, dim);
-		    CONSTRUCTOR_APPEND_ELT (vindex, cidx, index);
-		    CONSTRUCTOR_APPEND_ELT (vlen, cidx, len);
-		    CONSTRUCTOR_APPEND_ELT (vstride, cidx, stride);
-		  }
-
-		tree bias = size_zero_node;
-		tree volume = size_one_node;
-		tree enclosure = size_one_node;
-		for (i = dims - 1; i >= 0; i--)
-		  {
-		    tree dim = (*vdim)[i].value;
-		    tree index = (*vindex)[i].value;
-		    tree stride = (*vstride)[i].value;
-		    tree len = (*vlen)[i].value;
-
-		    /* For the bias we want, e.g.:
-
-			   index[0] * stride[0] * dim[1] * dim[2]
-			 + index[1] * stride[1] * dim[2]
-			 + index[2] * stride[2]
-
-		       All multiplied by "span" (or "elsize").  */
-
-		    tree index_stride = size_binop (MULT_EXPR, index, stride);
-		    bias = size_binop (PLUS_EXPR, bias,
-				       size_binop (MULT_EXPR, volume,
-						   index_stride));
-		    volume = size_binop (MULT_EXPR, volume, dim);
-
-		    if (i == 0)
-		      {
-			tree elems_covered = size_binop (MINUS_EXPR, len,
-							 size_one_node);
-			elems_covered = size_binop (MULT_EXPR, elems_covered,
-						    stride);
-			elems_covered = size_binop (PLUS_EXPR, elems_covered,
-						    size_one_node);
-			enclosure = size_binop (MULT_EXPR, enclosure,
-						elems_covered);
-		      }
-		    else
-		      enclosure = volume;
-		  }
-
-		/* If we don't have a separate span size, use the element size
-		   instead.  */
-		if (!span)
-		  span = fold_convert (sizetype, elsize);
-
-		/* The size of a volume enclosing the elements to be
-		   transferred.  */
-		OMP_CLAUSE_SIZE (oc) = size_binop (MULT_EXPR, enclosure, span);
-		/* And the bias of the first element we will update.  */
-		OMP_CLAUSE_SIZE (dn) = size_binop (MULT_EXPR, bias, span);
-
-		tree cdim = build_constructor (size_arr_type, vdim);
-		tree cindex = build_constructor (size_arr_type, vindex);
-		tree clen = build_constructor (size_arr_type, vlen);
-		tree cstride = build_constructor (size_arr_type, vstride);
-
-		if (TREE_STATIC (dim_tmp))
-		  DECL_INITIAL (dim_tmp) = cdim;
-		else
-		  gimplify_assign (dim_tmp, cdim, &ilist);
-
-		if (TREE_STATIC (index_tmp))
-		  DECL_INITIAL (index_tmp) = cindex;
-		else
-		  gimplify_assign (index_tmp, cindex, &ilist);
-
-		if (TREE_STATIC (len_tmp))
-		  DECL_INITIAL (len_tmp) = clen;
-		else
-		  gimplify_assign (len_tmp, clen, &ilist);
-
-		if (TREE_STATIC (stride_tmp))
-		  DECL_INITIAL (stride_tmp) = cstride;
-		else
-		  gimplify_assign (stride_tmp, cstride, &ilist);
-
-		tree desc_type = TREE_TYPE (desc);
-
-		tree ndims_field = TYPE_FIELDS (desc_type);
-		tree elemsize_field = DECL_CHAIN (ndims_field);
-		tree span_field = DECL_CHAIN (elemsize_field);
-		tree dim_field = DECL_CHAIN (span_field);
-		tree index_field = DECL_CHAIN (dim_field);
-		tree len_field = DECL_CHAIN (index_field);
-		tree stride_field = DECL_CHAIN (len_field);
-
-		vec<constructor_elt, va_gc> *v;
-		vec_alloc (v, 7);
-
-		bool all_static = (TREE_STATIC (dim_tmp)
-				   && TREE_STATIC (index_tmp)
-				   && TREE_STATIC (len_tmp)
-				   && TREE_STATIC (stride_tmp));
-
-		dim_tmp = build4 (ARRAY_REF, sizetype, dim_tmp, size_zero_node,
-				  NULL_TREE, NULL_TREE);
-		dim_tmp = build_fold_addr_expr (dim_tmp);
-
-		/* TODO: we could skip all-zeros index.  */
-		index_tmp = build4 (ARRAY_REF, sizetype, index_tmp,
-				    size_zero_node, NULL_TREE, NULL_TREE);
-		index_tmp = build_fold_addr_expr (index_tmp);
-
-		len_tmp = build4 (ARRAY_REF, sizetype, len_tmp, size_zero_node,
-				  NULL_TREE, NULL_TREE);
-		len_tmp = build_fold_addr_expr (len_tmp);
-
-		/* TODO: we could skip all-ones stride.  */
-		stride_tmp = build4 (ARRAY_REF, sizetype, stride_tmp,
-				     size_zero_node, NULL_TREE, NULL_TREE);
-		stride_tmp = build_fold_addr_expr (stride_tmp);
-
-		elsize = fold_convert (sizetype, elsize);
-		tree ndims = size_int (dims);
-
-		CONSTRUCTOR_APPEND_ELT (v, ndims_field, ndims);
-		CONSTRUCTOR_APPEND_ELT (v, elemsize_field, elsize);
-		CONSTRUCTOR_APPEND_ELT (v, span_field, span);
-		CONSTRUCTOR_APPEND_ELT (v, dim_field, dim_tmp);
-		CONSTRUCTOR_APPEND_ELT (v, index_field, index_tmp);
-		CONSTRUCTOR_APPEND_ELT (v, len_field, len_tmp);
-		CONSTRUCTOR_APPEND_ELT (v, stride_field, stride_tmp);
-
-		tree desc_ctor = build_constructor (desc_type, v);
-
-		if (all_static)
-		  {
-		    TREE_STATIC (desc) = 1;
-		    DECL_INITIAL (desc) = desc_ctor;
-		  }
-		else
-		  gimplify_assign (desc, desc_ctor, &ilist);
-
-		OMP_CLAUSE_CHAIN (dn) = OMP_CLAUSE_CHAIN (nc);
-		c = oc;
+		lower_omp_target_grid_desc (c, &ilist);
 		nc = c;
 	      }
 	    else if (!DECL_P (ovar))
-- 
2.53.0