diff mbox

[hsa] HSA: introduce more pure kernel information emission.

Message ID 55BF8578.2010303@suse.cz
State New
Headers show

Commit Message

Martin Liška Aug. 3, 2015, 3:15 p.m. UTC
Hello.

Following patch has been installed to HSA branch.

Thanks,
Martin
diff mbox

Patch

From 64f7f75a8b16dee2071fef7f546fbf6b06f82c4f Mon Sep 17 00:00:00 2001
From: mliska <mliska@suse.cz>
Date: Fri, 31 Jul 2015 17:53:57 +0200
Subject: [PATCH 1/3] HSA: introduce more pure kernel information emission.

libgomp/ChangeLog:

2015-07-31  Martin Liska  <mliska@suse.cz>

	* plugin/plugin-hsa.c (struct hsa_kernel_description): New structure.
	(struct brig_image_desc): Use it.
	(struct kernel_info): Add omp_data_size member.
	(struct module_info): Remove unused field.
	(GOMP_OFFLOAD_load_image): Load the newly added format.
	(create_kernel_dispatch): Allocate exactly ammount of memory needed
	for OMP data passing.
	(init_single_kernel): Print the OMP memory.
	hsa.c (init_hsa_image): Use new structure.

gcc/ChangeLog:

2015-07-31  Martin Liska  <mliska@suse.cz>

	* hsa-brig.c (hsa_output_kernel_mapping): Serialize new data structure.
	* hsa-gen.c (hsa_function_representation::hsa_function_representation):
	Add new field.
	(gen_hsa_insns_for_kernel_call): Calculate maximum amount of memory
	needed for OMP data.
	(generate_hsa): Likewise.
	* hsa.c (hsa_add_kern_decl_mapping): New function.
	(hsa_get_decl_kernel_mapping_omp_size): Likewise.
	* hsa.h: Add declaration of these functions.
---
 gcc/hsa-brig.c              | 231 ++++++++++++++++++++++++++------------------
 gcc/hsa-gen.c               |  16 ++-
 gcc/hsa.c                   |  13 ++-
 gcc/hsa.h                   |   8 +-
 libgomp/hsa.c               |  35 +++----
 libgomp/plugin/plugin-hsa.c | 107 +++++---------------
 6 files changed, 209 insertions(+), 201 deletions(-)

diff --git a/gcc/hsa-brig.c b/gcc/hsa-brig.c
index 27c41a5..1cc0b22 100644
--- a/gcc/hsa-brig.c
+++ b/gcc/hsa-brig.c
@@ -1753,7 +1753,7 @@  hsa_output_kernel_mapping (tree brig_decl)
   unsigned map_count = hsa_get_number_decl_kernel_mappings ();
 
   tree int_num_of_kernels;
-  int_num_of_kernels = build_int_cst (integer_type_node, (int) map_count);
+  int_num_of_kernels = build_int_cst (uint32_type_node, map_count);
   tree kernel_num_index_type = build_index_type (int_num_of_kernels);
   tree host_functions_array_type = build_array_type (ptr_type_node,
 						     kernel_num_index_type);
@@ -1768,7 +1768,7 @@  hsa_output_kernel_mapping (tree brig_decl)
   tree host_functions_ctor = build_constructor (host_functions_array_type,
 						host_functions_vec);
   char tmp_name[64];
-  ASM_GENERATE_INTERNAL_LABEL (tmp_name, "hsa_host_functions", 1);
+  ASM_GENERATE_INTERNAL_LABEL (tmp_name, "__hsa_host_functions", 1);
   tree hsa_host_func_table = build_decl (UNKNOWN_LOCATION, VAR_DECL,
 					 get_identifier (tmp_name),
 					 host_functions_array_type);
@@ -1782,115 +1782,161 @@  hsa_output_kernel_mapping (tree brig_decl)
   DECL_INITIAL (hsa_host_func_table) = host_functions_ctor;
   varpool_node::finalize_decl (hsa_host_func_table);
 
-  int len = 0;
-  for (unsigned i = 0; i < map_count; ++i)
-    {
-      char *name = hsa_get_decl_kernel_mapping_name (i);
-      /* We add 1 for the terminating zero and 1 for an ampersand prefix.  */
-      len = len + strlen (name) + 2;
-    }
-  len++;
+  /* Following code emits list of kernel_info structures.  */
 
-  /* Kernel mapping is a list of string names terminated by '\0'.  */
-  char *buf = XNEWVEC (char, len);
-  char *p = buf;
-  for (unsigned i = 0; i < map_count; ++i)
-    {
-      char *name = hsa_get_decl_kernel_mapping_name (i);
-      int ll = strlen (name);
-      gcc_assert (ll > 0);
-      *p = '&';
-      p++;
-      memcpy (p, name, ll);
-      p += ll;
-      *p = '\0';
-      p++;
-    }
-  *p = '\0';
-  tree kern_names = build_string (len, buf);
-  TREE_TYPE (kern_names) = build_array_type (char_type_node,
-					     build_index_type (size_int (len)));
-  free (buf);
+  tree kernel_info_type = make_node (RECORD_TYPE);
+  tree id_f1 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
+			   get_identifier ("name"), ptr_type_node);
+  DECL_CHAIN (id_f1) = NULL_TREE;
+  tree id_f2 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
+			   get_identifier ("omp_data_size"),
+			   unsigned_type_node);
+  DECL_CHAIN (id_f2) = id_f1;
+  tree id_f3 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
+			   get_identifier ("kernel_dependencies_count"),
+			   unsigned_type_node);
+  DECL_CHAIN (id_f3) = id_f2;
+  tree id_f4 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
+			   get_identifier ("kernel_dependencies"),
+			   build_pointer_type (build_pointer_type
+					       (char_type_node)));
+  DECL_CHAIN (id_f4) = id_f3;
+  finish_builtin_struct (kernel_info_type, "__hsa_kernel_info", id_f4,
+			 NULL_TREE);
 
-  /* Kernel dependencies is a list of lists, where for a given kernel A all
-     direct kernel dispatches to A1, A2, .., An are organized are joined by '.'
-     character and each entry in the list is separated by '\0'.  */
+  int_num_of_kernels = build_int_cstu (uint32_type_node, map_count);
+  tree kernel_info_vector_type = build_array_type
+    (kernel_info_type, build_index_type (int_num_of_kernels));
+
+  vec<constructor_elt, va_gc> *kernel_info_vector_vec = NULL;
+  tree kernel_dependencies_vector_type = NULL;
 
-  len = 0;
   for (unsigned i = 0; i < map_count; ++i)
     {
-      tree caller = hsa_get_decl_kernel_mapping_decl (i);
-
+      tree kernel = hsa_get_decl_kernel_mapping_decl (i);
+      char *name = hsa_get_decl_kernel_mapping_name (i);
+      unsigned len = strlen (name);
+      char *copy = XNEWVEC (char, len + 2);
+      copy[0] = '&';
+      memcpy (copy + 1, name, len);
+      copy[len + 1] = '\0';
+      len++;
+
+      tree kern_name = build_string (len, copy);
+      TREE_TYPE (kern_name) = build_array_type
+	(char_type_node, build_index_type (size_int (len)));
+      free (copy);
+
+      unsigned omp_size = hsa_get_decl_kernel_mapping_omp_size (i);
+      tree omp_data_size = build_int_cstu (uint32_type_node, omp_size);
+      unsigned count = 0;
+
+      kernel_dependencies_vector_type = build_array_type
+	(build_pointer_type (char_type_node),
+	 build_index_type (size_int (0)));
+
+      vec<constructor_elt, va_gc> *kernel_dependencies_vec = NULL;
       if (hsa_decl_kernel_dependencies)
 	{
-	  vec<char *> **slot = hsa_decl_kernel_dependencies->get (caller);
+	  vec<char *> **slot = hsa_decl_kernel_dependencies->get (kernel);
 	  if (slot)
 	    {
-	      vec<char *> *s = *slot;
-	      for (unsigned i = 0; i < s->length (); i++)
-		len += (strlen ((*s)[i]) + 1);
+	      vec <char *> *dependencies = *slot;
+	      count = dependencies->length ();
+
+	      kernel_dependencies_vector_type = build_array_type
+		(build_pointer_type (char_type_node),
+		 build_index_type (size_int (count)));
 
-	      /* Add N-1 dot characters.  */
-	      len += 2 * (s->length () - 1);
+	      for (unsigned j = 0; j < count; j++)
+		{
+		  char *d = (*dependencies)[j];
+		  len = strlen (d);
+		  tree dependency_name = build_string (len, d);
+		  TREE_TYPE (dependency_name) = build_array_type
+		    (char_type_node, build_index_type (size_int (len)));
+
+		  CONSTRUCTOR_APPEND_ELT
+		    (kernel_dependencies_vec, NULL_TREE,
+		     build1 (ADDR_EXPR,
+			     build_pointer_type (TREE_TYPE (dependency_name)),
+			     dependency_name));
+		}
 	    }
 	}
 
-      /* Zero termination character.  */
-      ++len;
-    }
+      tree dependencies_count = build_int_cstu (uint32_type_node, count);
 
-  buf = XNEWVEC (char, len);
-  p = buf;
-  for (unsigned i = 0; i < map_count; ++i)
-    {
-      tree caller = hsa_get_decl_kernel_mapping_decl (i);
+      vec<constructor_elt, va_gc> *kernel_info_vec = NULL;
+      CONSTRUCTOR_APPEND_ELT (kernel_info_vec, NULL_TREE,
+			      build1 (ADDR_EXPR,
+				      build_pointer_type (TREE_TYPE
+							  (kern_name)),
+				      kern_name));
+      CONSTRUCTOR_APPEND_ELT (kernel_info_vec, NULL_TREE, omp_data_size);
+      CONSTRUCTOR_APPEND_ELT (kernel_info_vec, NULL_TREE, dependencies_count);
 
-      if (hsa_decl_kernel_dependencies)
+      tree kernel_info_ctor = build_constructor (kernel_info_type,
+						 kernel_info_vec);
+
+      if (count > 0)
 	{
-	  vec<char *> **slot = hsa_decl_kernel_dependencies->get (caller);
-	  if (slot)
-	    {
-	      vec<char *> *s = *slot;
-	      unsigned k, j = 0;
-	      for (k = 0; k < s->length (); k++)
-		{
-		  unsigned ll = strlen ((*s)[k]);
-		  gcc_assert (ll > 0);
-		  memcpy (p, (*s)[k], ll);
-		  p += ll;
-		  *p = '\0';
-		  p++;
-
-		  /* If it is not a last elements, append '.' string.  */
-		  if (j != s->length () - 1)
-		    {
-		      *p++ = '.';
-		      *p++ = '\0';
-		    }
-
-		  j++;
-		}
-	    }
+	  ASM_GENERATE_INTERNAL_LABEL (tmp_name, "__hsa_dependencies_list", i);
+	  tree dependencies_list = build_decl (UNKNOWN_LOCATION, VAR_DECL,
+					       get_identifier (tmp_name),
+					       kernel_dependencies_vector_type);
+
+	  TREE_STATIC (dependencies_list) = 1;
+	  TREE_READONLY (dependencies_list) = 1;
+	  TREE_PUBLIC (dependencies_list) = 0;
+	  DECL_ARTIFICIAL (dependencies_list) = 1;
+	  DECL_IGNORED_P (dependencies_list) = 1;
+	  DECL_EXTERNAL (dependencies_list) = 0;
+	  TREE_CONSTANT (dependencies_list) = 1;
+	  DECL_INITIAL (dependencies_list) = build_constructor
+	    (kernel_dependencies_vector_type, kernel_dependencies_vec);
+	  varpool_node::finalize_decl (dependencies_list);
+
+	  CONSTRUCTOR_APPEND_ELT (kernel_info_vec, NULL_TREE,
+				  build1 (ADDR_EXPR,
+					  build_pointer_type
+					    (TREE_TYPE (dependencies_list)),
+					  dependencies_list));
 	}
+      else
+	CONSTRUCTOR_APPEND_ELT (kernel_info_vec, NULL_TREE, null_pointer_node);
 
-      /* Zero termination character.  */
-      *p++ = '\0';
+      CONSTRUCTOR_APPEND_ELT (kernel_info_vector_vec, NULL_TREE,
+			      kernel_info_ctor);
     }
 
-  tree kern_dependencies = build_string (len, buf);
-  TREE_TYPE (kern_dependencies) = build_array_type
-    (char_type_node, build_index_type (size_int (len)));
-  free (buf);
+  ASM_GENERATE_INTERNAL_LABEL (tmp_name, "__hsa_kernels", 1);
+  tree hsa_kernels = build_decl (UNKNOWN_LOCATION, VAR_DECL,
+				 get_identifier (tmp_name),
+				 kernel_info_vector_type);
+
+  TREE_STATIC (hsa_kernels) = 1;
+  TREE_READONLY (hsa_kernels) = 1;
+  TREE_PUBLIC (hsa_kernels) = 0;
+  DECL_ARTIFICIAL (hsa_kernels) = 1;
+  DECL_IGNORED_P (hsa_kernels) = 1;
+  DECL_EXTERNAL (hsa_kernels) = 0;
+  TREE_CONSTANT (hsa_kernels) = 1;
+  DECL_INITIAL (hsa_kernels) = build_constructor (kernel_info_vector_type,
+						  kernel_info_vector_vec);
+  varpool_node::finalize_decl (hsa_kernels);
 
   tree hsa_image_desc_type = make_node (RECORD_TYPE);
-  tree id_f1 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
+  id_f1 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
 			   get_identifier ("brig_module"), ptr_type_node);
   DECL_CHAIN (id_f1) = NULL_TREE;
-  tree id_f2 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
-			   get_identifier ("kern_names"), ptr_type_node);
+  id_f2 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
+			   get_identifier ("kernel_count"),
+			   unsigned_type_node);
+
   DECL_CHAIN (id_f2) = id_f1;
-  tree id_f3 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
-			   get_identifier ("kern_dependencies"),
+  id_f3 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
+			   get_identifier ("hsa_kernel_infos"),
 			   ptr_type_node);
   DECL_CHAIN (id_f3) = id_f2;
   finish_builtin_struct (hsa_image_desc_type, "__hsa_image_desc", id_f3,
@@ -1900,19 +1946,16 @@  hsa_output_kernel_mapping (tree brig_decl)
   CONSTRUCTOR_APPEND_ELT (img_desc_vec, NULL_TREE,
 			  build_fold_addr_expr (brig_decl));
   CONSTRUCTOR_APPEND_ELT (img_desc_vec, NULL_TREE,
-			  build1 (ADDR_EXPR,
-				  build_pointer_type (TREE_TYPE (kern_names)),
-				  kern_names));
+			  build_int_cstu (unsigned_type_node, map_count));
   CONSTRUCTOR_APPEND_ELT (img_desc_vec, NULL_TREE,
 			  build1 (ADDR_EXPR,
 				  build_pointer_type (TREE_TYPE
-						      (kern_dependencies)),
-				  kern_dependencies));
-
+						      (hsa_kernels)),
+				  hsa_kernels));
 
   tree img_desc_ctor = build_constructor (hsa_image_desc_type, img_desc_vec);
 
-  ASM_GENERATE_INTERNAL_LABEL (tmp_name, "hsa_img_descriptor", 1);
+  ASM_GENERATE_INTERNAL_LABEL (tmp_name, "__hsa_img_descriptor", 1);
   tree hsa_img_descriptor = build_decl (UNKNOWN_LOCATION, VAR_DECL,
 					get_identifier (tmp_name),
 					hsa_image_desc_type);
@@ -1948,7 +1991,7 @@  hsa_output_kernel_mapping (tree brig_decl)
   CONSTRUCTOR_APPEND_ELT (libgomp_host_table_vec, NULL_TREE, null_pointer_node);
   tree libgomp_host_table_ctor = build_constructor (libgomp_host_table_type,
 						    libgomp_host_table_vec);
-  ASM_GENERATE_INTERNAL_LABEL (tmp_name, "hsa_libgomp_host_table", 1);
+  ASM_GENERATE_INTERNAL_LABEL (tmp_name, "__hsa_libgomp_host_table", 1);
   tree hsa_libgomp_host_table = build_decl (UNKNOWN_LOCATION, VAR_DECL,
 					    get_identifier (tmp_name),
 					    libgomp_host_table_type);
diff --git a/gcc/hsa-gen.c b/gcc/hsa-gen.c
index 9784cb8..58ca26c 100644
--- a/gcc/hsa-gen.c
+++ b/gcc/hsa-gen.c
@@ -186,6 +186,7 @@  hsa_function_representation::hsa_function_representation ()
   called_functions = vNULL;
   shadow_reg = NULL;
   kernel_dispatch_count = 0;
+  maximum_omp_data_size = 0;
 }
 
 /* Destructor of class holding function/kernel-wide informaton and state.  */
@@ -2572,6 +2573,14 @@  gen_hsa_insns_for_kernel_call (hsa_bb *hbb, gcall *call)
 
   tree argument = gimple_call_arg (call, 1);
   gcc_assert (TREE_CODE (argument) == ADDR_EXPR);
+  tree d = TREE_TYPE (TREE_OPERAND (argument, 0));
+  unsigned omp_data_size = tree_to_uhwi
+    (TYPE_SIZE_UNIT (d));
+  gcc_checking_assert (omp_data_size > 0);
+
+  if (omp_data_size > hsa_cfun->maximum_omp_data_size)
+    hsa_cfun->maximum_omp_data_size = omp_data_size;
+
   hsa_symbol *var_decl = get_symbol_for_decl (TREE_OPERAND (argument, 0));
 
   hbb->append_insn (new (hsa_allocp_inst_comment)
@@ -3201,9 +3210,6 @@  generate_hsa (bool kernel)
     = xstrdup (get_declaration_name (current_function_decl));
   hsa_sanitize_name (hsa_cfun->name);
 
-  if (hsa_cfun->kern_p)
-    hsa_add_kern_decl_mapping (current_function_decl, hsa_cfun->name);
-
   gen_function_def_parameters (hsa_cfun, &ssa_map);
   if (seen_error ())
     goto fail;
@@ -3211,6 +3217,10 @@  generate_hsa (bool kernel)
   if (seen_error ())
     goto fail;
 
+  if (hsa_cfun->kern_p)
+    hsa_add_kern_decl_mapping (current_function_decl, hsa_cfun->name,
+			       hsa_cfun->maximum_omp_data_size);
+
 #ifdef ENABLE_CHECKING
   for (unsigned i = 0; i < ssa_map.length (); i++)
     if (ssa_map[i])
diff --git a/gcc/hsa.c b/gcc/hsa.c
index 2c02a82..b857342 100644
--- a/gcc/hsa.c
+++ b/gcc/hsa.c
@@ -84,6 +84,8 @@  struct GTY(()) hsa_decl_kernel_map_element
   tree decl;
   /* Name of the HSA kernel in BRIG.  */
   char * GTY((skip)) name;
+  /* Size of OMP data, if the kernel contains a kernel dispatch.  */
+  unsigned omp_data_size;
 };
 
 /* Mapping between decls and corresponding HSA kernels in this compilation
@@ -319,11 +321,12 @@  hsa_destroy_insn (hsa_insn_basic *insn)
 /* Create a mapping between the original function DECL and kernel name NAME.  */
 
 void
-hsa_add_kern_decl_mapping (tree decl, char *name)
+hsa_add_kern_decl_mapping (tree decl, char *name, unsigned omp_data_size)
 {
   hsa_decl_kernel_map_element dkm;
   dkm.decl = decl;
   dkm.name = name;
+  dkm.omp_data_size = omp_data_size;
   vec_safe_push (hsa_decl_kernel_mapping, dkm);
 }
 
@@ -351,6 +354,14 @@  hsa_get_decl_kernel_mapping_name (unsigned i)
   return (*hsa_decl_kernel_mapping)[i].name;
 }
 
+/* Return maximum OMP size for kernel decl name mapping.  */
+
+unsigned
+hsa_get_decl_kernel_mapping_omp_size (unsigned i)
+{
+  return (*hsa_decl_kernel_mapping)[i].omp_data_size;
+}
+
 /* Free the mapping between original decls and kernel names.  */
 
 void
diff --git a/gcc/hsa.h b/gcc/hsa.h
index c9102f6..eec5f17 100644
--- a/gcc/hsa.h
+++ b/gcc/hsa.h
@@ -821,6 +821,11 @@  public:
 
   /* Number of kernel dispatched which take place in the function.  */
   unsigned kernel_dispatch_count;
+
+  /* If the function representation contains a kernel dispatch,
+     OMP data size is necessary memory that is used for copying before
+     a kernel dispatch.  */
+  unsigned maximum_omp_data_size;
 };
 
 /* in hsa.c */
@@ -837,10 +842,11 @@  unsigned hsa_type_bit_size (BrigType16_t t);
 BrigType16_t hsa_bittype_for_type (BrigType16_t t);
 bool hsa_type_float_p (BrigType16_t type);
 void hsa_destroy_insn (hsa_insn_basic *insn);
-void hsa_add_kern_decl_mapping (tree decl, char *name);
+void hsa_add_kern_decl_mapping (tree decl, char *name, unsigned);
 unsigned hsa_get_number_decl_kernel_mappings (void);
 tree hsa_get_decl_kernel_mapping_decl (unsigned i);
 char *hsa_get_decl_kernel_mapping_name (unsigned i);
+unsigned hsa_get_decl_kernel_mapping_omp_size (unsigned i);
 void hsa_free_decl_kernel_mapping (void);
 void hsa_add_kernel_dependency (tree caller, char *called_function);
 void hsa_sanitize_name (char *p);
diff --git a/libgomp/hsa.c b/libgomp/hsa.c
index bda822b..b7c1a71 100644
--- a/libgomp/hsa.c
+++ b/libgomp/hsa.c
@@ -39,10 +39,19 @@  struct hsa_program_info
   hsa_executable_t executable;
 };
 
+struct hsa_kernel_description
+{
+  const char *name;
+  uint32_t omp_data_size;
+  uint32_t kernel_dependencies_count;
+  const char **kernel_dependencies;
+};
+
 struct hsa_image_desc
 {
   hsa_ext_module_t module;
-  const char *names;
+  const uint32_t kernel_count;
+  struct hsa_kernel_description *kernel_infos;
 };
 
 struct hsa_kernel_info
@@ -238,27 +247,17 @@  init_hsa_image (struct hsa_image_info *ii)
   struct hsa_one_image *img = ii->first_image;
   while (img)
     {
-      const char *p;
-      int count = 0;
+      int count = img->image_descriptor->kernel_count;
       struct hsa_kernel_info *kernel;
 
       status = hsa_ext_program_add_module (hsa_program.handle,
 					   img->image_descriptor->module);
+
       if (status != HSA_STATUS_SUCCESS)
 	gomp_fatal ("Could not add a module to the HSA program");
       if (debug)
 	fprintf (stderr, "Added a module to the HSA program\n");
 
-      p = img->image_descriptor->names;
-      while (*p)
-	{
-	  count++;
-	  do
-	    p++;
-	  while (*p);
-	  p++;
-	}
-
       if (debug)
 	fprintf (stderr, "Encountered %d kernels an image\n", count);
       img->kernels = gomp_malloc_cleared (sizeof (struct hsa_kernel_info)
@@ -266,17 +265,13 @@  init_hsa_image (struct hsa_image_info *ii)
       if (!img->kernels)
 	gomp_fatal ("Could not allocate memory for HSA kertnel descriptors");
 
-      p = img->image_descriptor->names;
       kernel = img->kernels;
-      while (*p)
+      for (unsigned i = 0; i < count; i++)
 	{
-	  kernel->name = p;
+	  kernel->name = img->image_descriptor->kernel_infos[i].name;
 	  kernel++;
-	  do
-	    p++;
-	  while (*p);
-	  p++;
 	}
+
       img = img->next;
     }
 
diff --git a/libgomp/plugin/plugin-hsa.c b/libgomp/plugin/plugin-hsa.c
index c5af705..144548a 100644
--- a/libgomp/plugin/plugin-hsa.c
+++ b/libgomp/plugin/plugin-hsa.c
@@ -60,14 +60,22 @@  hsa_fatal (const char *str, hsa_status_t status)
   GOMP_PLUGIN_fatal ("HSA fatal error: %s (%s)", str, hsa_error);
 }
 
+struct hsa_kernel_description
+{
+  const char *name;
+  unsigned omp_data_size;
+  unsigned kernel_dependencies_count;
+  const char **kernel_dependencies;
+};
+
 /* Data passed by the static initializer of a compilation unit containing BRIG
    to GOMP_offload_register.  */
 
 struct brig_image_desc
 {
   hsa_ext_module_t brig_module;
-  const char *names;
-  const char *kernel_dependencies;
+  const unsigned kernel_count;
+  struct hsa_kernel_description *kernel_infos;
 };
 
 struct agent_info;
@@ -78,6 +86,8 @@  struct kernel_info
 {
   /* Name of the kernel, required to locate it within the brig module.  */
   const char *name;
+  /* Size of memory space for OMP data.  */
+  unsigned omp_data_size;
   /* The specific agent the kernel has been or will be finalized for and run
      on.  */
   struct agent_info *agent;
@@ -115,8 +125,6 @@  struct module_info
 
   /* Number of kernels in this module.  */
   int kernel_count;
-  /* Number of kernel from kernel dispatches.  */
-  unsigned kernel_dispatch_count;
   /* An array of kernel_info structures describing each kernel in this
      module.  */
   struct kernel_info kernels[];
@@ -442,8 +450,7 @@  GOMP_OFFLOAD_load_image (int ord, void *target_data,
   struct addr_pair *pair;
   struct module_info *module;
   struct kernel_info *kernel;
-  int kernel_count = 0;
-  const char *p;
+  int kernel_count = image_desc->kernel_count;
 
   agent = get_agent_info (ord);
   if (pthread_rwlock_wrlock (&agent->modules_rwlock))
@@ -451,15 +458,6 @@  GOMP_OFFLOAD_load_image (int ord, void *target_data,
   if (agent->prog_finalized)
     destroy_hsa_program (agent);
 
-  p = image_desc->names;
-  while (*p)
-    {
-      kernel_count++;
-      do
-	p++;
-      while (*p);
-      p++;
-    }
   if (kernel_count == 0)
     GOMP_PLUGIN_fatal ("No kernels encountered in a brig module description");
   if (debug)
@@ -472,84 +470,27 @@  GOMP_OFFLOAD_load_image (int ord, void *target_data,
   module->image_desc = image_desc;
   module->kernel_count = kernel_count;
 
-  p = image_desc->names;
   kernel = &module->kernels[0];
 
-  /* Parse all kernels.  */
-  while (*p)
+  /* Allocate memory for kernel dependencies.  */
+  for (unsigned i = 0; i < kernel_count; i++)
     {
       pair->start = (uintptr_t) kernel;
       pair->end = (uintptr_t) (kernel + 1);
-      kernel->name = p;
+
+      struct hsa_kernel_description *d = &image_desc->kernel_infos[i];
       kernel->agent = agent;
       kernel->module = module;
+      kernel->name = d->name;
+      kernel->omp_data_size = d->omp_data_size;
+      kernel->dependencies_count = d->kernel_dependencies_count;
+      kernel->dependencies = d->kernel_dependencies;
       if (pthread_mutex_init (&kernel->init_mutex, NULL))
 	GOMP_PLUGIN_fatal ("Failed to initialize an HSA kernel mutex");
+
       kernel++;
       pair++;
-      do
-	p++;
-      while (*p);
-      p++;
-    }
-
-  /* Load length of kernel dependencies.  */
-  p = image_desc->kernel_dependencies;
-  unsigned i = 0;
-  do
-    {
-      while (*p != 0)
-	{
-	  if (*p == '.')
-	    p += 2;
-	  else
-	    {
-	      module->kernels[i].dependencies_count++;
-	      module->kernel_dispatch_count++;
-
-	      do
-		p++;
-	      while (*p);
-	      p++;
-	    }
-	}
-
-      i++;
-      p++;
-    }
-  while (i <= kernel_count - 1);
-
-  /* Allocate memory for kernel dependencies.  */
-  for (unsigned i = 0; i < kernel_count; i++)
-    module->kernels[i].dependencies = GOMP_PLUGIN_malloc
-      (sizeof (char *) * module->kernels[i].dependencies_count);
-
-  /* Parse all kernel dependencies.  */
-  p = image_desc->kernel_dependencies;
-  i = 0;
-
-  do
-    {
-      int j = 0;
-      while (*p != 0)
-	{
-	  if (*p == '.')
-	    p += 2;
-	  else
-	    {
-	      module->kernels[i].dependencies[j++] = p;
-
-	      do
-		p++;
-	      while (*p);
-	      p++;
-	    }
-	}
-
-      i++;
-      p++;
     }
-  while (i <= kernel_count - 1);
 
   add_module_to_agent (agent, module);
   if (pthread_rwlock_unlock (&agent->modules_rwlock))
@@ -641,7 +582,7 @@  create_kernel_dispatch (struct kernel_info *kernel)
   shadow->queue = agent->command_q;
 
   /* Compute right size needed for memory allocation.  */
-  shadow->omp_data_memory = GOMP_PLUGIN_malloc (100);
+  shadow->omp_data_memory = GOMP_PLUGIN_malloc (kernel->omp_data_size);
 
   unsigned dispatch_count = kernel->dependencies_count;
   shadow->kernel_dispatch_count = dispatch_count;
@@ -738,6 +679,8 @@  init_single_kernel (struct kernel_info *kernel)
 	       (unsigned) kernel->private_segment_size);
       fprintf (stderr, "  kernarg_segment_size: %u\n",
 	       (unsigned) kernel->kernarg_segment_size);
+      fprintf (stderr, "  omp_data_size: %u\n",
+	       kernel->omp_data_size);
     }
 }
 
-- 
2.4.6