The next two patches are the bulk of the compiler patch in the middle-ends.

The first patch here, implements the creation of dynamic array descriptors to
pass to the runtime, a different way than completely using map-clauses.

Because we support arbitrary number of dimensions, adding more map kind cases
may convolute a lot of the compiler/runtime logic handling the long map 
sequences.

This implementation uses a descriptor struct created on stack, and passes the
pointer to descriptor through to the libgomp runtime, using the exact same 
receiver field
for the dynamic array.

The libgomp runtime then does its stuff to set things up, and properly adjusts 
the device-side
receiver field pointer to the on-device created dynamic array structures. I.e. 
the same receiver
field serves as descriptor address field on the compiler side, and as the 
actual data address
once we get to device code (a pretty important point needed to clarify).

Thanks,
Chung-Lin

        gcc/
        * omp-low.c (struct omp_context):
        Add 'hash_map<tree_operand_hash, tree> *dynamic_arrays' field, also
        added include of "tree-hash-traits.h".
        (append_field_to_record_type): New function.
        (create_dynamic_array_descr_type): Likewise.
        (create_dynamic_array_descr_init_code): Likewise.
        (new_omp_context): Add initialize of dynamic_arrays field.
        (delete_omp_context): Add delete of dynamic_arrays field.
        (scan_sharing_clauses): For dynamic array map kinds, check for
        supported dimension structure, and install dynamic array variable into
        current omp_context.
        (lower_omp_target): Add handling for dynamic array map kinds.
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 6a1cb05..4c44800 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -60,6 +60,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "hsa-common.h"
 #include "stringpool.h"
 #include "attribs.h"
+#include "tree-hash-traits.h"
 
 /* Lowering of OMP parallel and workshare constructs proceeds in two
    phases.  The first phase scans the function looking for OMP statements
@@ -124,6 +125,9 @@ struct omp_context
 
   /* True if this construct can be cancelled.  */
   bool cancellable;
+
+  /* Hash map of dynamic arrays in this context.  */
+  hash_map<tree_operand_hash, tree> *dynamic_arrays;
 };
 
 static splay_tree all_contexts;
@@ -843,6 +847,136 @@ omp_copy_decl (tree var, copy_body_data *cb)
   return error_mark_node;
 }
 
+/* Helper function for create_dynamic_array_descr_type(), to append a new field
+   to a record type.  */
+
+static void
+append_field_to_record_type (tree record_type, tree fld_ident, tree fld_type)
+{
+  tree *p, fld = build_decl (UNKNOWN_LOCATION, FIELD_DECL, fld_ident, 
fld_type);
+  DECL_CONTEXT (fld) = record_type;
+
+  for (p = &TYPE_FIELDS (record_type); *p; p = &DECL_CHAIN (*p))
+    ;
+  *p = fld;
+}
+
+/* Create type for dynamic array descriptor. Returns created type, and
+   returns the number of dimensions in *DIM_NUM.  */
+
+static tree
+create_dynamic_array_descr_type (tree decl, tree dims, int *dim_num)
+{
+  int n = 0;
+  tree da_descr_type, name, x;
+  gcc_assert (TREE_CODE (dims) == TREE_LIST);
+
+  da_descr_type = lang_hooks.types.make_type (RECORD_TYPE);
+  name = create_tmp_var_name (".omp_dynamic_array_descr_type");
+  name = build_decl (UNKNOWN_LOCATION, TYPE_DECL, name, da_descr_type);
+  DECL_ARTIFICIAL (name) = 1;
+  DECL_NAMELESS (name) = 1;
+  TYPE_NAME (da_descr_type) = name;
+  TYPE_ARTIFICIAL (da_descr_type) = 1;
+
+  /* Main starting pointer/array.  */
+  tree main_var_type = TREE_TYPE (decl);
+  if (TREE_CODE (main_var_type) == REFERENCE_TYPE)
+    main_var_type = TREE_TYPE (main_var_type);
+  append_field_to_record_type (da_descr_type, DECL_NAME (decl),
+                              (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
+                               ? main_var_type
+                               : build_pointer_type (main_var_type)));
+  /* Number of dimensions.  */
+  append_field_to_record_type (da_descr_type, get_identifier ("$dim_num"),
+                              sizetype);
+
+  for (x = dims; x; x = TREE_CHAIN (x), n++)
+    {
+      char *fldname;
+      /* One for the start index.  */
+      ASM_FORMAT_PRIVATE_NAME (fldname, "$dim_base", n);
+      append_field_to_record_type (da_descr_type, get_identifier (fldname),
+                                  sizetype);
+      /* One for the length.  */
+      ASM_FORMAT_PRIVATE_NAME (fldname, "$dim_length", n);
+      append_field_to_record_type (da_descr_type, get_identifier (fldname),
+                                  sizetype);
+      /* One for the element size.  */
+      ASM_FORMAT_PRIVATE_NAME (fldname, "$dim_elem_size", n);
+      append_field_to_record_type (da_descr_type, get_identifier (fldname),
+                                  sizetype);
+      /* One for is_array flag.  */
+      ASM_FORMAT_PRIVATE_NAME (fldname, "$dim_is_array", n);
+      append_field_to_record_type (da_descr_type, get_identifier (fldname),
+                                  sizetype);
+    }
+
+  layout_type (da_descr_type);
+  *dim_num = n;
+  return da_descr_type;
+}
+
+/* Generate code sequence for initializing dynamic array descriptor.  */
+
+static void
+create_dynamic_array_descr_init_code (tree da_descr, tree da_var,
+                                     tree dimensions, int da_dim_num,
+                                     gimple_seq *ilist)
+{
+  tree fld, fldref;
+  tree da_descr_type = TREE_TYPE (da_descr);
+  tree dim_type = TREE_TYPE (da_var);
+
+  fld = TYPE_FIELDS (da_descr_type);
+  fldref = omp_build_component_ref (da_descr, fld);
+  gimplify_assign (fldref, (TREE_CODE (dim_type) == ARRAY_TYPE
+                           ? build_fold_addr_expr (da_var) : da_var), ilist);
+
+  if (TREE_CODE (dim_type) == REFERENCE_TYPE)
+    dim_type = TREE_TYPE (dim_type);
+
+  fld = TREE_CHAIN (fld);
+  fldref = omp_build_component_ref (da_descr, fld);
+  gimplify_assign (fldref, build_int_cst (sizetype, da_dim_num), ilist);
+
+  while (dimensions)
+    {
+      tree dim_base = fold_convert (sizetype, TREE_PURPOSE (dimensions));
+      tree dim_length = fold_convert (sizetype, TREE_VALUE (dimensions));
+      tree dim_elem_size = TYPE_SIZE_UNIT (TREE_TYPE (dim_type));
+      tree dim_is_array = (TREE_CODE (dim_type) == ARRAY_TYPE
+                          ? integer_one_node : integer_zero_node);
+      /* Set base.  */
+      fld = TREE_CHAIN (fld);
+      fldref = omp_build_component_ref (da_descr, fld);
+      dim_base = fold_build2 (MULT_EXPR, sizetype, dim_base, dim_elem_size);
+      gimplify_assign (fldref, dim_base, ilist);
+
+      /* Set length.  */
+      fld = TREE_CHAIN (fld);
+      fldref = omp_build_component_ref (da_descr, fld);
+      dim_length = fold_build2 (MULT_EXPR, sizetype, dim_length, 
dim_elem_size);
+      gimplify_assign (fldref, dim_length, ilist);
+
+      /* Set elem_size.  */
+      fld = TREE_CHAIN (fld);
+      fldref = omp_build_component_ref (da_descr, fld);
+      dim_elem_size = fold_convert (sizetype, dim_elem_size);
+      gimplify_assign (fldref, dim_elem_size, ilist);
+
+      /* Set is_array flag.  */
+      fld = TREE_CHAIN (fld);
+      fldref = omp_build_component_ref (da_descr, fld);
+      dim_is_array = fold_convert (sizetype, dim_is_array);
+      gimplify_assign (fldref, dim_is_array, ilist);
+
+      dimensions = TREE_CHAIN (dimensions);
+      dim_type = TREE_TYPE (dim_type);
+    }
+  gcc_assert (TREE_CHAIN (fld) == NULL_TREE);
+}
+
 /* Create a new context, with OUTER_CTX being the surrounding context.  */
 
 static omp_context *
@@ -877,6 +1011,8 @@ new_omp_context (gimple *stmt, omp_context *outer_ctx)
 
   ctx->cb.decl_map = new hash_map<tree, tree>;
 
+  ctx->dynamic_arrays = new hash_map<tree_operand_hash, tree>;
+
   return ctx;
 }
 
@@ -951,6 +1087,8 @@ delete_omp_context (splay_tree_value value)
   if (is_task_ctx (ctx))
     finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
 
+  delete ctx->dynamic_arrays;
+
   XDELETE (ctx);
 }
 
@@ -1256,6 +1394,42 @@ scan_sharing_clauses (tree clauses, omp_context *ctx,
              install_var_local (decl, ctx);
              break;
            }
+
+         if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
+             && GOMP_MAP_DYNAMIC_ARRAY_P (OMP_CLAUSE_MAP_KIND (c)))
+           {
+             tree da_decl = OMP_CLAUSE_DECL (c);
+             tree da_dimensions = OMP_CLAUSE_SIZE (c);
+             tree da_type = TREE_TYPE (da_decl);
+             bool by_ref = (TREE_CODE (da_type) == ARRAY_TYPE
+                            ? true : false);
+
+             /* Checking code to ensure we only have arrays at top dimension.
+                This limitation might be lifted in the future.  */
+             if (TREE_CODE (da_type) == REFERENCE_TYPE)
+               da_type = TREE_TYPE (da_type);
+             tree t = da_type, prev_t = NULL_TREE;
+             while (t)
+               {
+                 if (TREE_CODE (t) == ARRAY_TYPE && prev_t)
+                   {
+                     error_at (gimple_location (ctx->stmt), "array types are"
+                               " only allowed at outermost dimension of"
+                               " dynamic array");
+                     break;
+                   }
+                 prev_t = t;
+                 t = TREE_TYPE (t);
+               }
+
+             install_var_field (da_decl, by_ref, 3, ctx);
+             tree new_var = install_var_local (da_decl, ctx);
+
+             bool existed = ctx->dynamic_arrays->put (new_var, da_dimensions);
+             gcc_assert (!existed);
+             break;
+           }
+
          if (DECL_P (decl))
            {
              if (DECL_SIZE (decl)
@@ -7687,6 +7861,15 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, 
omp_context *ctx)
          case GOMP_MAP_FORCE_PRESENT:
          case GOMP_MAP_FORCE_DEVICEPTR:
          case GOMP_MAP_DEVICE_RESIDENT:
+         case GOMP_MAP_DYNAMIC_ARRAY_TO:
+         case GOMP_MAP_DYNAMIC_ARRAY_FROM:
+         case GOMP_MAP_DYNAMIC_ARRAY_TOFROM:
+         case GOMP_MAP_DYNAMIC_ARRAY_FORCE_TO:
+         case GOMP_MAP_DYNAMIC_ARRAY_FORCE_FROM:
+         case GOMP_MAP_DYNAMIC_ARRAY_FORCE_TOFROM:
+         case GOMP_MAP_DYNAMIC_ARRAY_ALLOC:
+         case GOMP_MAP_DYNAMIC_ARRAY_FORCE_ALLOC:
+         case GOMP_MAP_DYNAMIC_ARRAY_FORCE_PRESENT:
          case GOMP_MAP_LINK:
            gcc_assert (is_gimple_omp_oacc (stmt));
            break;
@@ -7749,7 +7932,14 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, 
omp_context *ctx)
        if (offloaded && !(OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
                           && OMP_CLAUSE_MAP_IN_REDUCTION (c)))
          {
-           x = build_receiver_ref (var, true, ctx);
+           tree var_type = TREE_TYPE (var);
+           bool rcv_by_ref =
+             (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
+              && GOMP_MAP_DYNAMIC_ARRAY_P (OMP_CLAUSE_MAP_KIND (c))
+              && TREE_CODE (var_type) != ARRAY_TYPE
+              ? false : true);
+
+           x = build_receiver_ref (var, rcv_by_ref, ctx);
            tree new_var = lookup_decl (var, ctx);
 
            if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
@@ -7993,6 +8183,25 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, 
omp_context *ctx)
                    avar = build_fold_addr_expr (avar);
                    gimplify_assign (x, avar, &ilist);
                  }
+               else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
+                        && (OMP_CLAUSE_MAP_KIND (c) & GOMP_MAP_DYNAMIC_ARRAY))
+                 {
+                   int da_dim_num;
+                   tree dimensions = OMP_CLAUSE_SIZE (c);
+
+                   tree da_descr_type =
+                     create_dynamic_array_descr_type (OMP_CLAUSE_DECL (c),
+                                                      dimensions, &da_dim_num);
+                   tree da_descr =
+                     create_tmp_var_raw (da_descr_type, ".$omp_da_descr");
+                   gimple_add_tmp_var (da_descr);
+
+                   create_dynamic_array_descr_init_code
+                     (da_descr, ovar, dimensions, da_dim_num, &ilist);
+
+                   gimplify_assign (x, build_fold_addr_expr (da_descr),
+                                    &ilist);
+                 }
                else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
                  {
                    gcc_assert (is_gimple_omp_oacc (ctx->stmt));
@@ -8053,6 +8262,9 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, 
omp_context *ctx)
                  s = TREE_TYPE (s);
                s = TYPE_SIZE_UNIT (s);
              }
+           else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
+                    && (OMP_CLAUSE_MAP_KIND (c) & GOMP_MAP_DYNAMIC_ARRAY))
+             s = NULL_TREE;
            else
              s = OMP_CLAUSE_SIZE (c);
            if (s == NULL_TREE)

Reply via email to