This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[HSA] Back-end enhancement and various fixes


Hello.

In the following series, I enhance HSA BE to correctly support aggregate types (as function call arguments and return types).
Apart from that, we should not ICE in situations where we have a non-trivial memory reference. Finally, many memory leaks were
fixed and a lot of refactoring is included.

Martin
>From c5006ca75912bdab8256fe4670645d5f1ad54a14 Mon Sep 17 00:00:00 2001
From: marxin <mliska@suse.cz>
Date: Mon, 26 Oct 2015 16:58:26 +0100
Subject: [PATCH 1/9] HSA: fix generation of address that end as SSA_NAME or
 VAR_DECL.

gcc/ChangeLog:

2015-10-22  Martin Liska  <mliska@suse.cz>

	* hsa-brig.c (emit_function_directives): Emit private variables.
	* hsa-gen.c (hsa_function_representation::~hsa_function_representation):
	Release the container.
	(hsa_function_representation::create_hsa_temporary): New function.
	(gen_hsa_addr): Handle properly SSA_NAMEs and VAR_DECLs.
	* hsa.h (hsa_function_representation::m_private_variables):
	Declare new variable.
---
 gcc/hsa-brig.c |  7 ++++++-
 gcc/hsa-gen.c  | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
 gcc/hsa.h      | 14 ++++++++++++++
 3 files changed, 70 insertions(+), 6 deletions(-)

diff --git a/gcc/hsa-brig.c b/gcc/hsa-brig.c
index be7ef59..0c26b58 100644
--- a/gcc/hsa-brig.c
+++ b/gcc/hsa-brig.c
@@ -626,6 +626,7 @@ emit_function_directives (hsa_function_representation *f, bool is_declaration)
 	if (TREE_CODE ((*iter)->m_decl) == VAR_DECL)
 	  count++;
       count += f->m_spill_symbols.length ();
+      count += f->m_private_variables.length ();
     }
 
   next_toplev_off = scoped_off + count * sizeof (struct BrigDirectiveVariable);
@@ -685,7 +686,11 @@ emit_function_directives (hsa_function_representation *f, bool is_declaration)
 	  emit_directive_variable (sym);
 	  brig_insn_count++;
 	}
-
+      for (unsigned i = 0; i < f->m_private_variables.length (); i++)
+	{
+	  emit_directive_variable (f->m_private_variables[i]);
+	  brig_insn_count++;
+	}
     }
 
   return ptr_to_fndir;
diff --git a/gcc/hsa-gen.c b/gcc/hsa-gen.c
index c36c9e0..15f9050 100644
--- a/gcc/hsa-gen.c
+++ b/gcc/hsa-gen.c
@@ -228,10 +228,10 @@ hsa_function_representation::hsa_function_representation
   (tree fdecl, bool kernel_p): m_name (NULL),
   m_input_args_count (0), m_reg_count (0), m_input_args (NULL),
   m_output_arg (NULL), m_spill_symbols (vNULL), m_readonly_variables (vNULL),
-  m_called_functions (vNULL), m_hbb_count (0), m_in_ssa (true),
-  m_kern_p (kernel_p), m_declaration_p (false), m_decl (fdecl),
+  m_private_variables (vNULL), m_called_functions (vNULL), m_hbb_count (0),
+  m_in_ssa (true), m_kern_p (kernel_p), m_declaration_p (false), m_decl (fdecl),
   m_shadow_reg (NULL), m_kernel_dispatch_count (0), m_maximum_omp_data_size (0),
-  m_seen_error (false)
+  m_seen_error (false), m_temp_symbol_count (0)
 {
   int sym_init_len = (vec_safe_length (cfun->local_decls) / 2) + 1;;
   m_local_symbols = new hash_table <hsa_noop_symbol_hasher> (sym_init_len);
@@ -251,6 +251,7 @@ hsa_function_representation::~hsa_function_representation ()
 
   m_spill_symbols.release ();
   m_readonly_variables.release ();
+  m_private_variables.release ();
   m_called_functions.release ();
 }
 
@@ -284,6 +285,24 @@ bool hsa_function_representation::has_shadow_reg_p ()
   return m_shadow_reg != NULL;
 }
 
+void
+hsa_function_representation::init_extra_bbs ()
+{
+  hsa_init_new_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun));
+  hsa_init_new_bb (EXIT_BLOCK_PTR_FOR_FN (cfun));
+}
+
+hsa_symbol *
+hsa_function_representation::create_hsa_temporary (BrigType16_t type)
+{
+  hsa_symbol *s = new hsa_symbol (type, BRIG_SEGMENT_PRIVATE,
+				  BRIG_LINKAGE_FUNCTION);
+  s->m_name_number = m_temp_symbol_count++;
+
+  hsa_cfun->m_private_variables.safe_push (s);
+  return s;
+}
+
 /* Allocate HSA structures that we need only while generating with this.  */
 
 static void
@@ -1711,6 +1730,13 @@ process_mem_base (tree base, hsa_symbol **symbol, BrigType16_t *addrtype,
     gcc_unreachable ();
 }
 
+/* Forward declaration of a function.  */
+
+static void
+gen_hsa_addr_insns (tree val, hsa_op_reg *dest, hsa_bb *hbb,
+		    vec <hsa_op_reg_p> *ssa_map);
+
+
 /* Generate HSA address operand for a given tree memory reference REF.  If
    instructions need to be created to calculate the address, they will be added
    to the end of HBB, SSA_MAP is an array mapping gimple SSA names to HSA
@@ -1731,6 +1757,7 @@ gen_hsa_addr (tree ref, hsa_bb *hbb, vec <hsa_op_reg_p> *ssa_map,
   tree varoffset = NULL_TREE;
   BrigType16_t addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
   HOST_WIDE_INT bitsize = 0, bitpos = 0;
+  BrigType16_t flat_addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
 
   if (TREE_CODE (ref) == STRING_CST)
     {
@@ -1762,8 +1789,27 @@ gen_hsa_addr (tree ref, hsa_bb *hbb, vec <hsa_op_reg_p> *ssa_map,
   switch (TREE_CODE (ref))
     {
     case ADDR_EXPR:
-      gcc_unreachable ();
+      {
+	addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_PRIVATE);
+	symbol = hsa_cfun->create_hsa_temporary (flat_addrtype);
+	hsa_op_reg *r = new hsa_op_reg (flat_addrtype);
+	gen_hsa_addr_insns (ref, r, hbb, ssa_map);
+	hbb->append_insn (new hsa_insn_mem (BRIG_OPCODE_ST, r->m_type,
+					    r, new hsa_op_address (symbol)));
+
+	break;
+      }
+    case SSA_NAME:
+      {
+	addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_PRIVATE);
+	symbol = hsa_cfun->create_hsa_temporary (flat_addrtype);
+	hsa_op_reg *r = hsa_reg_for_gimple_ssa (ref, ssa_map);
+
+	hbb->append_insn (new hsa_insn_mem (BRIG_OPCODE_ST, r->m_type,
+					    r, new hsa_op_address (symbol)));
 
+	break;
+      }
     case PARM_DECL:
     case VAR_DECL:
     case RESULT_DECL:
@@ -1821,7 +1867,6 @@ gen_hsa_addr (tree ref, hsa_bb *hbb, vec <hsa_op_reg_p> *ssa_map,
       HSA_SORRY_AT (EXPR_LOCATION (origref),
 		    "support for HSA does not implement function pointers");
       goto out;
-    case SSA_NAME:
     default:
       HSA_SORRY_ATV (EXPR_LOCATION (origref), "support for HSA does "
 		     "not implement memory access to %E", origref);
diff --git a/gcc/hsa.h b/gcc/hsa.h
index 3c83d61..d38255f 100644
--- a/gcc/hsa.h
+++ b/gcc/hsa.h
@@ -940,6 +940,14 @@ public:
      shadow register.  */
   bool has_shadow_reg_p ();
 
+  /* The entry/exit blocks don't contain incoming code,
+     but the HSA generator might use them to put code into,
+     so we need hsa_bb instances of them.  */
+  void init_extra_bbs ();
+
+  /* Create a private symbol of requested TYPE.  */
+  hsa_symbol *create_hsa_temporary (BrigType16_t type);
+
   /* Name of the function.  */
   char *m_name;
 
@@ -967,6 +975,9 @@ public:
      noni-addressable variables with a constructor).  */
   vec <struct hsa_symbol *> m_readonly_variables;
 
+  /* Private function artificial variables.  */
+  vec <struct hsa_symbol *> m_private_variables;
+
   /* Vector of called function declarations.  */
   vec <tree> m_called_functions;
 
@@ -998,6 +1009,9 @@ public:
 
   /* Return true if there's an HSA-specific warning already seen.  */
   bool m_seen_error;
+
+  /* Counter for temporary symbols created in the function representation.  */
+  unsigned m_temp_symbol_count;
 };
 
 enum hsa_function_kind
-- 
2.6.2

>From 592d9c22f378067002ffb6d852049e7ae7acb787 Mon Sep 17 00:00:00 2001
From: marxin <mliska@suse.cz>
Date: Mon, 26 Oct 2015 17:04:28 +0100
Subject: [PATCH 2/9] HSA: Support aggregate type as a function return type.

gcc/ChangeLog:

2015-10-22  Martin Liska  <mliska@suse.cz>

	* hsa-gen.c (gen_hsa_insns_for_direct_call): Support aggregate
	type as a function return type.
	(gen_hsa_insns_for_return): Likewise.
	(hsa_symbol::total_byte_size): New function.
	* hsa.h (struct hsa_symbol): Declare it.
---
 gcc/hsa-gen.c | 82 +++++++++++++++++++++++++++++++++++------------------------
 gcc/hsa.h     |  6 +++++
 2 files changed, 55 insertions(+), 33 deletions(-)

diff --git a/gcc/hsa-gen.c b/gcc/hsa-gen.c
index 15f9050..94e50c8 100644
--- a/gcc/hsa-gen.c
+++ b/gcc/hsa-gen.c
@@ -221,6 +221,25 @@ hsa_symbol::hsa_symbol (BrigType16_t type, BrigSegment8_t segment,
 {
 }
 
+void *
+hsa_symbol::operator new (size_t)
+{
+  return hsa_allocp_symbols->vallocate ();
+}
+
+unsigned HOST_WIDE_INT
+hsa_symbol::total_byte_size ()
+{
+  unsigned HOST_WIDE_INT s = hsa_type_bit_size (~BRIG_TYPE_ARRAY_MASK & m_type);
+  gcc_assert (s % BITS_PER_UNIT == 0);
+  s /= BITS_PER_UNIT;
+
+  if (m_dim)
+    s *= m_dim;
+
+  return s;
+}
+
 /* Constructor of class representing global HSA function/kernel information and
    state.  */
 
@@ -3243,14 +3262,6 @@ gen_hsa_insns_for_direct_call (gimple *stmt, hsa_bb *hbb,
   hsa_insn_mem *result_insn = NULL;
   if (!VOID_TYPE_P (result_type))
     {
-      if (AGGREGATE_TYPE_P (result_type))
-	{
-	  HSA_SORRY_ATV (gimple_location (stmt),
-			 "support for HSA does not implement returning a value "
-			 "which is of an aggregate type %T", result_type);
-	  return;
-	}
-
       hsa_op_address *addr = gen_hsa_addr_for_arg (result_type, -1);
 
       /* Even if result of a function call is unused, we have to emit
@@ -3258,25 +3269,25 @@ gen_hsa_insns_for_direct_call (gimple *stmt, hsa_bb *hbb,
       if (result)
 	{
 	  tree lhs_type = TREE_TYPE (result);
-	  if (AGGREGATE_TYPE_P (lhs_type))
-	    {
-	      HSA_SORRY_ATV (gimple_location (stmt), "support for HSA does not "
-			     "implement assignment of a returned value "
-			     "which is of an aggregate type %T", lhs_type);
-	      return;
-	    }
-
-	  BrigType16_t mtype = mem_type_for_type
-	    (hsa_type_for_scalar_tree_type (lhs_type, false));
 
 	  if (hsa_seen_error ())
 	    return;
 
-	  hsa_op_reg *dst = hsa_reg_for_gimple_ssa (result, ssa_map);
-
-	  result_insn = new hsa_insn_mem (BRIG_OPCODE_LD, mtype, dst, addr);
+	  if (AGGREGATE_TYPE_P (lhs_type))
+	    {
+	      hsa_op_address *result_addr = gen_hsa_addr (result, hbb, ssa_map);
+	      gen_hsa_memory_copy (hbb, result_addr, addr,
+				   addr->m_symbol->total_byte_size ());
+	    }
+	  else
+	    {
+	      BrigType16_t mtype = mem_type_for_type
+		(hsa_type_for_scalar_tree_type (lhs_type, false));
 
-	  hbb->append_insn (result_insn);
+	      hsa_op_reg *dst = hsa_reg_for_gimple_ssa (result, ssa_map);
+	      result_insn = new hsa_insn_mem (BRIG_OPCODE_LD, mtype, dst, addr);
+	      hbb->append_insn (result_insn);
+	    }
 	}
 
       call_insn->m_output_arg = addr->m_symbol;
@@ -3314,21 +3325,26 @@ gen_hsa_insns_for_return (greturn *stmt, hsa_bb *hbb,
   tree retval = gimple_return_retval (stmt);
   if (retval)
     {
+      hsa_op_address *addr = new hsa_op_address (hsa_cfun->m_output_arg);
+
       if (AGGREGATE_TYPE_P (TREE_TYPE (retval)))
 	{
-	  HSA_SORRY_AT (gimple_location (stmt),
-			"HSA does not support return "
-			"statement with an aggregate value type");
-	  return;
+	  hsa_op_address *retval_addr = gen_hsa_addr (retval, hbb, ssa_map);
+	  gen_hsa_memory_copy (hbb, addr, retval_addr,
+			       hsa_cfun->m_output_arg->total_byte_size ());
 	}
+      else
+	{
+	  BrigType16_t mtype = mem_type_for_type
+	    (hsa_type_for_scalar_tree_type (TREE_TYPE (retval), false));
 
-      /* Store of return value.  */
-      BrigType16_t mtype = mem_type_for_type
-	(hsa_type_for_scalar_tree_type (TREE_TYPE (retval), false));
-      hsa_op_address *addr = new hsa_op_address (hsa_cfun->m_output_arg);
-      hsa_op_base *src = hsa_reg_or_immed_for_gimple_op (retval, hbb, ssa_map);
-      hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, mtype, src, addr);
-      hbb->append_insn (mem);
+	  /* Store of return value.  */
+	  hsa_op_base *src = hsa_reg_or_immed_for_gimple_op (retval, hbb,
+							     ssa_map);
+	  hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, mtype, src,
+						addr);
+	  hbb->append_insn (mem);
+	}
     }
 
   /* HSAIL return instruction emission.  */
diff --git a/gcc/hsa.h b/gcc/hsa.h
index d38255f..f4184f9 100644
--- a/gcc/hsa.h
+++ b/gcc/hsa.h
@@ -60,6 +60,12 @@ struct hsa_symbol
   hsa_symbol (BrigType16_t type, BrigSegment8_t segment,
 	      BrigLinkage8_t linkage);
 
+  /* New operator to allocate HSA symbol from pool alloc.  */
+  void *operator new (size_t);
+
+  /* Return total size of the symbol.  */
+  unsigned HOST_WIDE_INT total_byte_size ();
+
   /* Pointer to the original tree, which is PARM_DECL for input parameters and
      RESULT_DECL for the output parameters.  */
   tree m_decl;
-- 
2.6.2

>From 5b148fbe1110bcc8a7c826163451e04743b84143 Mon Sep 17 00:00:00 2001
From: marxin <mliska@suse.cz>
Date: Mon, 26 Oct 2015 17:05:09 +0100
Subject: [PATCH 3/9] HSA: convert actual argument types to formal types.

gcc/ChangeLog:

2015-10-16  Martin Liska  <mliska@suse.cz>

	* hsa-gen.c (gen_hsa_insns_for_direct_call): Convert types of actual
	arguments to formal types arguments.
	(get_format_argument_type): New function.
	(hsa_reg_for_gimple_ssa): Fix coding style.
---
 gcc/hsa-gen.c | 48 +++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 41 insertions(+), 7 deletions(-)

diff --git a/gcc/hsa-gen.c b/gcc/hsa-gen.c
index 94e50c8..050475c 100644
--- a/gcc/hsa-gen.c
+++ b/gcc/hsa-gen.c
@@ -1130,7 +1130,7 @@ hsa_reg_for_gimple_ssa (tree ssa, vec <hsa_op_reg_p> *ssa_map)
   if ((*ssa_map)[SSA_NAME_VERSION (ssa)])
     return (*ssa_map)[SSA_NAME_VERSION (ssa)];
 
-  hreg = new  hsa_op_reg (hsa_type_for_scalar_tree_type (TREE_TYPE (ssa),
+  hreg = new hsa_op_reg (hsa_type_for_scalar_tree_type (TREE_TYPE (ssa),
 							 true));
   hreg->m_gimple_ssa = ssa;
   (*ssa_map)[SSA_NAME_VERSION (ssa)] = hreg;
@@ -3201,6 +3201,20 @@ verify_function_arguments (tree decl)
     }
 }
 
+/* Return BRIG type for FORMAL_ARG_TYPE.  If the formal argument type is NULL,
+   return ACTUAL_ARG_TYPE.  */
+
+static BrigType16_t
+get_format_argument_type (tree formal_arg_type, BrigType16_t actual_arg_type)
+{
+  if (formal_arg_type == NULL)
+    return actual_arg_type;
+
+  BrigType16_t decl_type = hsa_type_for_scalar_tree_type
+    (formal_arg_type, false);
+  return mem_type_for_type (decl_type);
+}
+
 /* Generate HSA instructions for a direct call instruction.
    Instructions will be appended to HBB, which also needs to be the
    corresponding structure to the basic_block of STMT. SSA_MAP maps gimple SSA
@@ -3223,11 +3237,15 @@ gen_hsa_insns_for_direct_call (gimple *stmt, hsa_bb *hbb,
     (BRIG_KIND_DIRECTIVE_ARG_BLOCK_START, call_insn);
   hbb->append_insn (arg_start);
 
+  tree parm_type_chain = TYPE_ARG_TYPES (gimple_call_fntype (stmt));
+
   /* Preparation of arguments that will be passed to function.  */
   const unsigned args = gimple_call_num_args (stmt);
   for (unsigned i = 0; i < args; ++i)
     {
       tree parm = gimple_call_arg (stmt, (int)i);
+      tree parm_decl_type = parm_type_chain != NULL_TREE
+	? TREE_VALUE (parm_type_chain) : NULL_TREE;
 
       if (AGGREGATE_TYPE_P (TREE_TYPE (parm)))
 	{
@@ -3237,20 +3255,36 @@ gen_hsa_insns_for_direct_call (gimple *stmt, hsa_bb *hbb,
 	  return;
 	}
 
-      BrigType16_t mtype = mem_type_for_type (hsa_type_for_scalar_tree_type
-					      (TREE_TYPE (parm), false));
+      hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (parm, hbb,
+							      ssa_map);
+      if (parm_decl_type != NULL && AGGREGATE_TYPE_P (parm_decl_type))
+	{
+	  HSA_SORRY_AT (gimple_location (stmt),
+			"support for HSA does not implement an aggregate "
+			"formal argument in a function call, while actual "
+			"argument is not an aggregate");
+	  return;
+	}
 
+      BrigType16_t formal_arg_type = get_format_argument_type
+	(parm_decl_type, src->m_type);
       if (hsa_seen_error ())
 	return;
 
-      hsa_op_address *addr = gen_hsa_addr_for_arg (TREE_TYPE (parm), i);
-      hsa_op_base *src = hsa_reg_or_immed_for_gimple_op (parm, hbb, ssa_map);
-      hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, mtype, src, addr);
+      if (src->m_type != formal_arg_type)
+	src = src->get_in_type (formal_arg_type, hbb);
+
+      hsa_op_address *addr = gen_hsa_addr_for_arg
+	(parm_decl_type != NULL_TREE ? parm_decl_type: TREE_TYPE (parm), i);
+      hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, formal_arg_type,
+					    src, addr);
 
-      call_insn->m_input_args.safe_push (addr->m_symbol);
       hbb->append_insn (mem);
 
+      call_insn->m_input_args.safe_push (addr->m_symbol);
       call_insn->m_args_symbols.safe_push (addr->m_symbol);
+      if (parm_type_chain)
+	parm_type_chain = TREE_CHAIN (parm_type_chain);
     }
 
   call_insn->m_args_code_list = new hsa_op_code_list (args);
-- 
2.6.2

>From 93f9684b50033e3c68e80ec0fbb25d992e1cafdf Mon Sep 17 00:00:00 2001
From: marxin <mliska@suse.cz>
Date: Thu, 22 Oct 2015 18:22:15 +0200
Subject: [PATCH 4/9] HSA: handle taking an address of an argument.

gcc/ChangeLog:

2015-10-22  Martin Liska  <mliska@suse.cz>

	* hsa-gen.c(gen_hsa_insns_for_direct_call): Support aggregate argument
	types.
	(gen_function_def_parameters): Copy function arguments to private
	symbols.
---
 gcc/hsa-gen.c | 88 ++++++++++++++++++++++++++++++++++++-----------------------
 1 file changed, 54 insertions(+), 34 deletions(-)

diff --git a/gcc/hsa-gen.c b/gcc/hsa-gen.c
index 050475c..ec0762e 100644
--- a/gcc/hsa-gen.c
+++ b/gcc/hsa-gen.c
@@ -3246,40 +3246,44 @@ gen_hsa_insns_for_direct_call (gimple *stmt, hsa_bb *hbb,
       tree parm = gimple_call_arg (stmt, (int)i);
       tree parm_decl_type = parm_type_chain != NULL_TREE
 	? TREE_VALUE (parm_type_chain) : NULL_TREE;
+      hsa_op_address *addr;
 
       if (AGGREGATE_TYPE_P (TREE_TYPE (parm)))
 	{
-	  HSA_SORRY_AT (gimple_location (stmt),
-			"support for HSA does not "
-			"implement an aggregate argument in a function call");
-	  return;
+	  addr = gen_hsa_addr_for_arg (TREE_TYPE (parm), i);
+	  hsa_op_address *src = gen_hsa_addr (parm, hbb, ssa_map);
+	  gen_hsa_memory_copy (hbb, addr, src,
+			       addr->m_symbol->total_byte_size ());
 	}
-
-      hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (parm, hbb,
-							      ssa_map);
-      if (parm_decl_type != NULL && AGGREGATE_TYPE_P (parm_decl_type))
+      else
 	{
-	  HSA_SORRY_AT (gimple_location (stmt),
-			"support for HSA does not implement an aggregate "
-			"formal argument in a function call, while actual "
-			"argument is not an aggregate");
-	  return;
-	}
+	  hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (parm, hbb,
+								  ssa_map);
 
-      BrigType16_t formal_arg_type = get_format_argument_type
-	(parm_decl_type, src->m_type);
-      if (hsa_seen_error ())
-	return;
+	  if (parm_decl_type != NULL && AGGREGATE_TYPE_P (parm_decl_type))
+	    {
+	      HSA_SORRY_AT (gimple_location (stmt),
+			    "support for HSA does not implement an aggregate "
+			    "formal argument in a function call, while actual "
+			    "argument is not an aggregate");
+	      return;
+	    }
 
-      if (src->m_type != formal_arg_type)
-	src = src->get_in_type (formal_arg_type, hbb);
+	  BrigType16_t formal_arg_type = get_format_argument_type
+	    (parm_decl_type, src->m_type);
+	  if (hsa_seen_error ())
+	    return;
 
-      hsa_op_address *addr = gen_hsa_addr_for_arg
-	(parm_decl_type != NULL_TREE ? parm_decl_type: TREE_TYPE (parm), i);
-      hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, formal_arg_type,
-					    src, addr);
+	  if (src->m_type != formal_arg_type)
+	    src = src->get_in_type (formal_arg_type, hbb);
 
-      hbb->append_insn (mem);
+	  addr = gen_hsa_addr_for_arg
+	    (parm_decl_type != NULL_TREE ? parm_decl_type: TREE_TYPE (parm), i);
+	  hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, formal_arg_type,
+						src, addr);
+
+	  hbb->append_insn (mem);
+	}
 
       call_insn->m_input_args.safe_push (addr->m_symbol);
       call_insn->m_args_symbols.safe_push (addr->m_symbol);
@@ -4996,14 +5000,33 @@ gen_function_def_parameters (hsa_function_representation *f,
 
       f->m_input_args[i].m_segment = f->m_kern_p ? BRIG_SEGMENT_KERNARG :
 				       BRIG_SEGMENT_ARG;
-
       f->m_input_args[i].m_linkage = BRIG_LINKAGE_FUNCTION;
       f->m_input_args[i].m_name = hsa_get_declaration_name (parm);
+      hsa_symbol *arg = &f->m_input_args[i];
+
+      /* Copy all input arguments and create corresponding private symbols
+	 for them.  */
+      hsa_symbol *private_arg;
+      hsa_op_address *parm_addr = new hsa_op_address (arg);
 
-      slot = f->m_local_symbols->find_slot (&f->m_input_args[i],
-						INSERT);
+      if (TREE_ADDRESSABLE (parm)
+	  || (!is_gimple_reg (parm) && !TREE_READONLY (parm)))
+	{
+	  private_arg = hsa_cfun->create_hsa_temporary (arg->m_type);
+	  hsa_cfun->m_private_variables.safe_push (private_arg);
+	  fillup_sym_for_decl (parm, private_arg);
+	  f->m_private_variables.safe_push (private_arg);
+
+	  hsa_op_address *private_arg_addr = new hsa_op_address (private_arg);
+	  gen_hsa_memory_copy (prologue, private_arg_addr, parm_addr,
+			       arg->total_byte_size ());
+	}
+      else
+	private_arg = arg;
+
+      slot = f->m_local_symbols->find_slot (private_arg, INSERT);
       gcc_assert (!*slot);
-      *slot = &f->m_input_args[i];
+      *slot = private_arg;
 
       if (is_gimple_reg (parm))
 	{
@@ -5013,12 +5036,9 @@ gen_function_def_parameters (hsa_function_representation *f,
 	      BrigType16_t mtype = mem_type_for_type
 		(hsa_type_for_scalar_tree_type (TREE_TYPE (ddef), false));
 	      hsa_op_reg *dest = hsa_reg_for_gimple_ssa (ddef, ssa_map);
-	      hsa_op_address *addr;
-
-	      addr = gen_hsa_addr (parm, prologue, ssa_map);
 	      hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, mtype,
-						    dest, addr);
-	      gcc_assert (!addr->m_reg);
+						    dest, parm_addr);
+	      gcc_assert (!parm_addr->m_reg);
 	      prologue->append_insn (mem);
 	    }
 	}
-- 
2.6.2

>From a34342ce566bba60b12a550496b747370938cc52 Mon Sep 17 00:00:00 2001
From: marxin <mliska@suse.cz>
Date: Tue, 27 Oct 2015 11:58:12 +0100
Subject: [PATCH 5/9] HSA: hsa_symbol refactoring and memory allocation fix-up

gcc/ChangeLog:

	* hsa-brig.c (emit_function_directives): Simplify emission
	of private symbols.
	(emit_arg_block_insn): Use different property of hsa_symbol.
	(emit_insn): Remove usage of comment_instructions.
	(hsa_brig_emit_function): Properly release
	comment_instructions vector.
	* hsa-dump.c (dump_hsa_insn_1): Use different property of
	hsa_symbol.
	* hsa-gen.c (hsa_symbol::operator new):
	(hsa_symbol::fillup_for_decl): New function.
	(hsa_function_representation::~hsa_function_representation):
	Release memory.
	(hsa_function_representation::get_shadow_reg): Use ctor of
	hsa_symbol.
	(hsa_init_data_for_cfun): Remove BB allocation.
	(hsa_deinit_data_for_cfun): Call ctor for all insns.
	(fillup_sym_for_decl): Remove.
	(get_symbol_for_decl): Use ctor of hsa_symbol.
	(hsa_insn_basic::hsa_insn_basic): Register newly allocated
	instance in hsa_instances.
	(hsa_insn_call::~hsa_insn_call): Likewise.
	(gen_hsa_addr_for_arg): Use ctor of hsa_symbol.
	(gen_hsa_insns_for_direct_call): Do not push to remove
	container.
	(gen_hsa_insns_for_call): Small code refactoring.
	(get_function_arg_count): Remove function.
	(gen_function_decl_parameters): Use vector instread of
	dynamically allocated memory array.
	(gen_function_def_parameters): Do it method of
	hsa_function_representation.
	(hsa_generate_function_declaration): Use ctor instread of
	XCNEW.
	(convert_switch_statements): Release leaked memory.
	(emit_hsa_module_variables): Use newly added function
	init_extra_bbs.
	(generate_hsa): Do not use removed argument.
	* hsa.c (hsa_deinit_compilation_unit_data): Release
	hsa_num_threads.
	(hsa_destroy_insn): Handle hsa_insn_sbr and hsa_insn_comment.
	(hsa_init_compilation_unit_data): Initialize
	hsa_global_variable_symbols.
	(hsa_deinit_compilation_unit_data): Do not release deleted
	container.
	(hsa_fail_cfun): Do not initialize hsa_failed_functions.
	* hsa.h (struct hsa_symbol): Declare new methods and remove
	unused properties.
---
 gcc/hsa-brig.c |  50 +++--------
 gcc/hsa-dump.c |   6 +-
 gcc/hsa-gen.c  | 279 +++++++++++++++++++++++++++------------------------------
 gcc/hsa.c      |  22 +++--
 gcc/hsa.h      |  45 +++++-----
 5 files changed, 182 insertions(+), 220 deletions(-)

diff --git a/gcc/hsa-brig.c b/gcc/hsa-brig.c
index 0c26b58..a09415c 100644
--- a/gcc/hsa-brig.c
+++ b/gcc/hsa-brig.c
@@ -137,9 +137,6 @@ static hash_map <tree, BrigDirectiveExecutable *> *emitted_declarations;
 /* List of sbr instructions.  */
 static vec <hsa_insn_sbr *> *switch_instructions;
 
-/* List of comment instructions.  */
-static vec <hsa_insn_comment *> *comment_instructions;
-
 struct function_linkage_pair
 {
   function_linkage_pair (tree decl, unsigned int off):
@@ -615,16 +612,10 @@ emit_function_directives (hsa_function_representation *f, bool is_declaration)
   inarg_off = brig_code.total_size + sizeof(fndir)
     + (f->m_output_arg ? sizeof (struct BrigDirectiveVariable) : 0);
   scoped_off = inarg_off
-    + f->m_input_args_count * sizeof (struct BrigDirectiveVariable);
+    + f->m_input_args.length () * sizeof (struct BrigDirectiveVariable);
 
   if (!f->m_declaration_p)
     {
-      for (hash_table <hsa_noop_symbol_hasher>::iterator iter
-	     = f->m_local_symbols->begin ();
-	   iter != f->m_local_symbols->end ();
-	   ++iter)
-	if (TREE_CODE ((*iter)->m_decl) == VAR_DECL)
-	  count++;
       count += f->m_spill_symbols.length ();
       count += f->m_private_variables.length ();
     }
@@ -636,7 +627,7 @@ emit_function_directives (hsa_function_representation *f, bool is_declaration)
   fndir.base.kind = htole16 (f->m_kern_p ? BRIG_KIND_DIRECTIVE_KERNEL
 			     : BRIG_KIND_DIRECTIVE_FUNCTION);
   fndir.name = htole32 (name_offset);
-  fndir.inArgCount = htole16 (f->m_input_args_count);
+  fndir.inArgCount = htole16 (f->m_input_args.length ());
   fndir.outArgCount = htole16 (f->m_output_arg ? 1 : 0);
   fndir.firstInArg = htole32 (inarg_off);
   fndir.firstCodeBlockEntry = htole32 (scoped_off);
@@ -667,20 +658,11 @@ emit_function_directives (hsa_function_representation *f, bool is_declaration)
 
   if (f->m_output_arg)
     emit_directive_variable (f->m_output_arg);
-  for (unsigned i = 0; i < f->m_input_args_count; i++)
-    emit_directive_variable (&f->m_input_args[i]);
+  for (unsigned i = 0; i < f->m_input_args.length (); i++)
+    emit_directive_variable (f->m_input_args[i]);
 
   if (!f->m_declaration_p)
     {
-      for (hash_table <hsa_noop_symbol_hasher>::iterator iter
-	     = f->m_local_symbols->begin ();
-	   iter != f->m_local_symbols->end ();
-	   ++iter)
-	{
-	  if (TREE_CODE ((*iter)->m_decl) == VAR_DECL)
-	    brig_insn_count++;
-	  emit_directive_variable (*iter);
-	}
       for (int i = 0; f->m_spill_symbols.iterate (i, &sym); i++)
 	{
 	  emit_directive_variable (sym);
@@ -1526,7 +1508,7 @@ emit_cvt_insn (hsa_insn_basic *insn)
    within a call block instruction.  */
 
 static void
-emit_m_call_insn (hsa_insn_basic *insn)
+emit_call_insn (hsa_insn_basic *insn)
 {
   hsa_insn_call *call = dyn_cast <hsa_insn_call *> (insn);
   struct BrigInstBr repr;
@@ -1584,7 +1566,7 @@ emit_arg_block_insn (hsa_insn_arg_block *insn)
 	    brig_insn_count++;
 	  }
 
-	if (insn->m_call_insn->m_result_symbol)
+	if (insn->m_call_insn->m_output_arg)
 	  {
 	    insn->m_call_insn->m_result_code_list->m_offsets[0] = htole32
 	      (emit_directive_variable (insn->m_call_insn->m_output_arg));
@@ -1795,16 +1777,11 @@ emit_insn (hsa_insn_basic *insn)
     }
   if (hsa_insn_call *call = dyn_cast <hsa_insn_call *> (insn))
     {
-      emit_m_call_insn (call);
+      emit_call_insn (call);
       return;
     }
   if (hsa_insn_comment *comment = dyn_cast <hsa_insn_comment *> (insn))
     {
-      if (comment_instructions == NULL)
-	comment_instructions = new vec <hsa_insn_comment *> ();
-
-      comment_instructions->safe_push (comment);
-
       emit_comment_insn (comment);
       return;
     }
@@ -1915,6 +1892,10 @@ hsa_brig_emit_function (void)
 		hbb->m_label_ref.m_directive_offset;
 	    }
 	}
+
+      switch_instructions->release ();
+      delete switch_instructions;
+      switch_instructions = NULL;
     }
 
   if (dump_file)
@@ -1923,15 +1904,6 @@ hsa_brig_emit_function (void)
       dump_hsa_cfun (dump_file);
     }
 
-  if (comment_instructions)
-    for (unsigned i = 0; i < comment_instructions->length (); i++)
-      (*comment_instructions)[i]->release_string ();
-
-  delete switch_instructions;
-  switch_instructions = NULL;
-  delete comment_instructions;
-  comment_instructions = NULL;
-
   emit_queued_operands ();
 }
 
diff --git a/gcc/hsa-dump.c b/gcc/hsa-dump.c
index f926e39..1a68bc2 100644
--- a/gcc/hsa-dump.c
+++ b/gcc/hsa-dump.c
@@ -954,15 +954,15 @@ dump_hsa_insn_1 (FILE *f, hsa_insn_basic *insn, int *indent)
 
       fprintf (f, "call &%s", name);
 
-      if (call->m_result_symbol)
+      if (call->m_output_arg)
 	fprintf (f, "(%%res) ");
 
       fprintf (f, "(");
-      for (unsigned i = 0; i < call->m_args_symbols.length (); i++)
+      for (unsigned i = 0; i < call->m_input_args.length (); i++)
         {
 	  fprintf (f, "%%__arg_%u", i);
 
-	  if (i != call->m_args_symbols.length () - 1)
+	  if (i != call->m_input_args.length () - 1)
 	    fprintf (f, ", ");
 	}
       fprintf (f, ")");
diff --git a/gcc/hsa-gen.c b/gcc/hsa-gen.c
index ec0762e..4a30eb0 100644
--- a/gcc/hsa-gen.c
+++ b/gcc/hsa-gen.c
@@ -195,7 +195,9 @@ static object_allocator<hsa_insn_arg_block> *hsa_allocp_inst_arg_block;
 static object_allocator<hsa_insn_comment> *hsa_allocp_inst_comment;
 static object_allocator<hsa_insn_queue> *hsa_allocp_inst_queue;
 static object_allocator<hsa_bb> *hsa_allocp_bb;
-static object_allocator<hsa_symbol> *hsa_allocp_symbols;
+
+/* List of pointers to all instructions that come from an object allocator.  */
+static vec <hsa_insn_basic *> hsa_instructions;
 
 /* Vectors with selected instructions and operands that need
    a destruction.  */
@@ -221,12 +223,6 @@ hsa_symbol::hsa_symbol (BrigType16_t type, BrigSegment8_t segment,
 {
 }
 
-void *
-hsa_symbol::operator new (size_t)
-{
-  return hsa_allocp_symbols->vallocate ();
-}
-
 unsigned HOST_WIDE_INT
 hsa_symbol::total_byte_size ()
 {
@@ -240,12 +236,28 @@ hsa_symbol::total_byte_size ()
   return s;
 }
 
+/* Forward declaration.  */
+
+static BrigType16_t
+hsa_type_for_tree_type (const_tree type, unsigned HOST_WIDE_INT *dim_p,
+			bool min32int);
+
+void
+hsa_symbol::fillup_for_decl (tree decl)
+{
+  m_decl = decl;
+  m_type = hsa_type_for_tree_type (TREE_TYPE (decl), &m_dim, false);
+
+  if (hsa_seen_error ())
+    m_seen_error = true;
+}
+
 /* Constructor of class representing global HSA function/kernel information and
    state.  */
 
 hsa_function_representation::hsa_function_representation
   (tree fdecl, bool kernel_p): m_name (NULL),
-  m_input_args_count (0), m_reg_count (0), m_input_args (NULL),
+  m_reg_count (0), m_input_args (vNULL),
   m_output_arg (NULL), m_spill_symbols (vNULL), m_readonly_variables (vNULL),
   m_private_variables (vNULL), m_called_functions (vNULL), m_hbb_count (0),
   m_in_ssa (true), m_kern_p (kernel_p), m_declaration_p (false), m_decl (fdecl),
@@ -260,16 +272,28 @@ hsa_function_representation::hsa_function_representation
 
 hsa_function_representation::~hsa_function_representation ()
 {
-  delete m_local_symbols;
-  free (m_input_args);
-  free (m_output_arg);
   /* Kernel names are deallocated at the end of BRIG output when deallocating
      hsa_decl_kernel_mapping.  */
-  if (!m_kern_p)
+  if (!m_kern_p || m_seen_error)
     free (m_name);
 
+  for (unsigned i = 0; i < m_input_args.length (); i++)
+    delete m_input_args[i];
+  m_input_args.release ();
+
+  delete m_output_arg;
+  delete m_local_symbols;
+
+  for (unsigned i = 0; i < m_spill_symbols.length (); i++)
+    delete m_spill_symbols[i];
   m_spill_symbols.release ();
+
+  for (unsigned i = 0; i < m_readonly_variables.length (); i++)
+    delete m_readonly_variables[i];
   m_readonly_variables.release ();
+
+  for (unsigned i = 0; i < m_private_variables.length (); i++)
+    delete m_private_variables[i];
   m_private_variables.release ();
   m_called_functions.release ();
 }
@@ -283,10 +307,9 @@ hsa_function_representation::get_shadow_reg ()
     return m_shadow_reg;
 
   /* Append the shadow argument.  */
-  hsa_symbol *shadow = &m_input_args[m_input_args_count++];
-  shadow->m_type = BRIG_TYPE_U64;
-  shadow->m_segment = BRIG_SEGMENT_KERNARG;
-  shadow->m_linkage = BRIG_LINKAGE_FUNCTION;
+  hsa_symbol *shadow = new hsa_symbol (BRIG_TYPE_U64, BRIG_SEGMENT_KERNARG,
+				       BRIG_LINKAGE_FUNCTION);
+  m_input_args.safe_push (shadow);
   shadow->m_name = "hsa_runtime_shadow";
 
   hsa_op_reg *r = new hsa_op_reg (BRIG_TYPE_U64);
@@ -363,13 +386,6 @@ hsa_init_data_for_cfun ()
   hsa_allocp_inst_queue
     = new object_allocator<hsa_insn_queue> ("HSA queue instructions");
   hsa_allocp_bb = new object_allocator<hsa_bb> ("HSA basic blocks");
-  hsa_allocp_symbols = new object_allocator<hsa_symbol> ("HSA symbols");
-
-  /* The entry/exit blocks don't contain incoming code,
-     but the HSA generator might use them to put code into,
-     so we need hsa_bb instances of them.  */
-  hsa_init_new_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun));
-  hsa_init_new_bb (EXIT_BLOCK_PTR_FOR_FN (cfun));
 }
 
 /* Deinitialize HSA subsystem and free all allocated memory.  */
@@ -383,14 +399,6 @@ hsa_deinit_data_for_cfun (void)
     if (bb->aux)
       {
 	hsa_bb *hbb = hsa_bb_for_bb (bb);
-	hsa_insn_phi *phi;
-	for (phi = hbb->m_first_phi;
-	     phi;
-	     phi = phi->m_next ? as_a <hsa_insn_phi *> (phi->m_next): NULL)
-	  phi->~hsa_insn_phi ();
-	for (hsa_insn_basic *insn = hbb->m_first_insn; insn; insn = insn->m_next)
-	  hsa_destroy_insn (insn);
-
 	hbb->~hsa_bb ();
 	bb->aux = NULL;
       }
@@ -408,6 +416,11 @@ hsa_deinit_data_for_cfun (void)
   hsa_list_operand_reg.release ();
   hsa_list_operand_immed.release ();
 
+  for (unsigned i = 0; i < hsa_instructions.length (); i++)
+    hsa_destroy_insn (hsa_instructions[i]);
+
+  hsa_instructions.release ();
+
   delete hsa_allocp_operand_address;
   delete hsa_allocp_operand_immed;
   delete hsa_allocp_operand_reg;
@@ -426,7 +439,6 @@ hsa_deinit_data_for_cfun (void)
   delete hsa_allocp_inst_comment;
   delete hsa_allocp_inst_queue;
   delete hsa_allocp_bb;
-  delete hsa_allocp_symbols;
   delete hsa_cfun;
 }
 
@@ -694,28 +706,14 @@ hsa_needs_cvt (BrigType16_t dtype, BrigType16_t stype)
   return false;
 }
 
-/* Fill in those values into SYM according to DECL, which are determined
-   independently from whether it is parameter, result, or a variable, local or
-   global.  */
-
-static void
-fillup_sym_for_decl (tree decl, struct hsa_symbol *sym)
-{
-  sym->m_decl = decl;
-  sym->m_type = hsa_type_for_tree_type (TREE_TYPE (decl), &sym->m_dim);
-
-  if (hsa_seen_error ())
-    sym->m_seen_error = true;
-}
-
 /* Lookup or create the associated hsa_symbol structure with a given VAR_DECL
    or lookup the hsa_structure corresponding to a PARM_DECL.  */
 
 static hsa_symbol *
 get_symbol_for_decl (tree decl)
 {
-  struct hsa_symbol **slot;
-  struct hsa_symbol dummy, *sym;
+  hsa_symbol **slot, *sym;
+  hsa_symbol dummy (BRIG_TYPE_NONE, BRIG_SEGMENT_NONE, BRIG_LINKAGE_NONE);
 
   gcc_assert (TREE_CODE (decl) == PARM_DECL
 	      || TREE_CODE (decl) == RESULT_DECL
@@ -723,51 +721,47 @@ get_symbol_for_decl (tree decl)
 
   dummy.m_decl = decl;
 
-  if (TREE_CODE (decl) == VAR_DECL && is_global_var (decl))
+  slot = hsa_cfun->m_local_symbols->find_slot (&dummy, INSERT);
+  gcc_checking_assert (slot);
+  if (*slot)
     {
-      slot = hsa_global_variable_symbols->find_slot (&dummy, INSERT);
-      gcc_checking_assert (slot);
-      if (*slot)
-	{
-	  sym = *slot;
+      sym = *slot;
 
-	  /* If the symbol is problematic, mark current function also as
-	     problematic.  */
-	  if (sym->m_seen_error)
-	    hsa_fail_cfun ();
+      /* If the symbol is problematic, mark current function also as
+	 problematic.  */
+      if (sym->m_seen_error)
+	hsa_fail_cfun ();
 
-	  return sym;
-	}
-      sym = XCNEW (struct hsa_symbol);
-      sym->m_segment = BRIG_SEGMENT_GLOBAL;
-      sym->m_linkage = BRIG_LINKAGE_FUNCTION;
+      return sym;
+    }
+
+  if (TREE_CODE (decl) == VAR_DECL && is_global_var (decl))
+    {
+      sym = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_READONLY,
+			    BRIG_LINKAGE_MODULE);
 
       /* Following type of global variables can be handled.  */
       if (TREE_READONLY (decl) && !TREE_ADDRESSABLE (decl)
 	  && DECL_INITIAL (decl) && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
 	  && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == INTEGER_TYPE)
 	{
-	  sym->m_segment = BRIG_SEGMENT_READONLY;
-	  sym->m_linkage = BRIG_LINKAGE_MODULE;
 	  sym->m_cst_value = new hsa_op_immed (DECL_INITIAL (decl), false);
-	  hsa_cfun->m_readonly_variables.safe_push (sym);
 	}
       else
 	HSA_SORRY_ATV (EXPR_LOCATION (decl), "referring to global symbol "
 		       "%q+D by name from HSA code won't work", decl);
+
+      hsa_cfun->m_readonly_variables.safe_push (sym);
     }
   else
     {
-      slot = hsa_cfun->m_local_symbols->find_slot (&dummy, INSERT);
-      gcc_checking_assert (slot);
-      if (*slot)
-	return *slot;
       gcc_assert (TREE_CODE (decl) == VAR_DECL);
       sym = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_PRIVATE,
 			    BRIG_LINKAGE_FUNCTION);
+      hsa_cfun->m_private_variables.safe_push (sym);
     }
 
-  fillup_sym_for_decl (decl, sym);
+  sym->fillup_for_decl (decl);
   sym->m_name = hsa_get_declaration_name (decl);
   *slot = sym;
   return sym;
@@ -1161,6 +1155,8 @@ hsa_insn_basic::hsa_insn_basic (unsigned nops, int opc): m_prev (NULL),
 {
   if (nops > 0)
     operands.safe_grow_cleared (nops);
+
+  hsa_instructions.safe_push (this);
 }
 
 /* Make OP the operand number INDEX of operands of this instuction.  If OP is a
@@ -1250,6 +1246,8 @@ hsa_insn_basic::hsa_insn_basic (unsigned nops, int opc, BrigType16_t t,
       gcc_checking_assert (nops >= 4);
       set_op (3, arg3);
     }
+
+  hsa_instructions.safe_push (this);
 }
 
 /* New operator to allocate basic instruction from pool alloc.  */
@@ -1366,6 +1364,11 @@ hsa_insn_sbr::replace_all_labels (basic_block old_bb, basic_block new_bb)
       m_jump_table[i] = new_bb;
 }
 
+hsa_insn_sbr::~hsa_insn_sbr ()
+{
+  m_jump_table.release ();
+}
+
 /* Constructor of comparison instructin.  CMP is the comparison operation and T
    is the result type.  */
 
@@ -1498,7 +1501,7 @@ hsa_insn_seg::operator new (size_t)
 
 hsa_insn_call::hsa_insn_call (tree callee)
   : hsa_insn_basic (0, BRIG_OPCODE_CALL), m_called_function (callee),
-  m_args_code_list (NULL), m_result_symbol (NULL), m_result_code_list (NULL)
+  m_output_arg (NULL), m_args_code_list (NULL), m_result_code_list (NULL)
 {
 }
 
@@ -1510,6 +1513,17 @@ hsa_insn_call::operator new (size_t)
   return hsa_allocp_inst_call->vallocate ();
 }
 
+hsa_insn_call::~hsa_insn_call ()
+{
+  for (unsigned i = 0; i < m_input_args.length (); i++)
+    delete m_input_args[i];
+
+  delete m_output_arg;
+
+  m_input_args.release ();
+  m_input_arg_insns.release ();
+}
+
 /* Constructor of class representing the argument block required to invoke
    a call in HSAIL.  */
 hsa_insn_arg_block::hsa_insn_arg_block (BrigKind brig_kind,
@@ -1546,8 +1560,7 @@ hsa_insn_comment::operator new (size_t)
   return hsa_allocp_inst_comment->vallocate ();
 }
 
-void
-hsa_insn_comment::release_string ()
+hsa_insn_comment::~hsa_insn_comment ()
 {
   gcc_checking_assert (m_comment);
   free (m_comment);
@@ -1942,10 +1955,8 @@ out:
 static hsa_op_address *
 gen_hsa_addr_for_arg (tree tree_type, int index)
 {
-  hsa_symbol *sym = hsa_allocp_symbols->allocate ();
-  memset (sym, 0, sizeof (hsa_symbol));
-  sym->m_segment = BRIG_SEGMENT_ARG;
-  sym->m_linkage = BRIG_LINKAGE_ARG;
+  hsa_symbol *sym = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_ARG,
+				    BRIG_LINKAGE_ARG);
   sym->m_type = hsa_type_for_tree_type (tree_type, &sym->m_dim);
 
   if (index == -1) /* Function result.  */
@@ -3286,7 +3297,6 @@ gen_hsa_insns_for_direct_call (gimple *stmt, hsa_bb *hbb,
 	}
 
       call_insn->m_input_args.safe_push (addr->m_symbol);
-      call_insn->m_args_symbols.safe_push (addr->m_symbol);
       if (parm_type_chain)
 	parm_type_chain = TREE_CHAIN (parm_type_chain);
     }
@@ -3329,7 +3339,6 @@ gen_hsa_insns_for_direct_call (gimple *stmt, hsa_bb *hbb,
 	}
 
       call_insn->m_output_arg = addr->m_symbol;
-      call_insn->m_result_symbol = addr->m_symbol;
       call_insn->m_result_code_list = new hsa_op_code_list (1);
     }
   else
@@ -4537,9 +4546,9 @@ gen_hsa_insns_for_call (gimple *stmt, hsa_bb *hbb,
 	called = TREE_OPERAND (called, 0);
 	gcc_checking_assert (TREE_CODE (called) == FUNCTION_DECL);
 
-	char *name = xstrdup (hsa_get_declaration_name (called));
 	hsa_add_kernel_dependency
-	  (hsa_cfun->m_decl, hsa_brig_function_name (name));
+	  (hsa_cfun->m_decl,
+	   hsa_brig_function_name (hsa_get_declaration_name (called)));
 	gen_hsa_insns_for_kernel_call (hbb, as_a <gcall *> (stmt));
 
 	break;
@@ -4913,21 +4922,6 @@ gen_body_from_gimple (vec <hsa_op_reg_p> *ssa_map)
     }
 }
 
-/* For a function DECL, get number of arguments.  */
-
-static unsigned
-get_function_arg_count (tree decl)
-{
-  unsigned count = 0;
-
-  for (tree parm = TYPE_ARG_TYPES (TREE_TYPE (decl)); parm;
-       parm = TREE_CHAIN (parm))
-    count++;
-
-  /* Return type is the last element of tree list.  */
-  return count - 1;
-}
-
 static void
 gen_function_decl_parameters (hsa_function_representation *f,
 			      tree decl)
@@ -4935,32 +4929,31 @@ gen_function_decl_parameters (hsa_function_representation *f,
   tree parm;
   unsigned i;
 
-  f->m_input_args_count = get_function_arg_count (decl);
-  f->m_input_args = XCNEWVEC (hsa_symbol, f->m_input_args_count);
   for (parm = TYPE_ARG_TYPES (TREE_TYPE (decl)), i = 0;
        parm;
        parm = TREE_CHAIN (parm), i++)
     {
       /* Result type if last in the tree list.  */
-      if (i == f->m_input_args_count)
+      if (TREE_CHAIN (parm) == NULL)
 	break;
 
       tree v = TREE_VALUE (parm);
-      f->m_input_args[i].m_type = hsa_type_for_tree_type
-	(v, &f->m_input_args[i].m_dim);
-      f->m_input_args[i].m_segment = BRIG_SEGMENT_ARG;
-      f->m_input_args[i].m_linkage = BRIG_LINKAGE_NONE;
-      f->m_input_args[i].m_name_number = i;
+
+      hsa_symbol *arg = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_ARG,
+					BRIG_LINKAGE_NONE);
+      arg->m_type = hsa_type_for_tree_type (v, &arg->m_dim);
+      arg->m_name_number = i;
+
+      f->m_input_args.safe_push (arg);
     }
 
   tree result_type = TREE_TYPE (TREE_TYPE (decl));
   if (!VOID_TYPE_P (result_type))
     {
-      f->m_output_arg = XCNEW (hsa_symbol);
-      f->m_output_arg->m_type = hsa_type_for_tree_type (result_type,
-						      &f->m_output_arg->m_dim);
-      f->m_output_arg->m_segment = BRIG_SEGMENT_ARG;
-      f->m_output_arg->m_linkage = BRIG_LINKAGE_NONE;
+      f->m_output_arg = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_ARG,
+					BRIG_LINKAGE_NONE);
+      f->m_output_arg->m_type = hsa_type_for_tree_type
+	(result_type, &f->m_output_arg->m_dim);
       f->m_output_arg->m_name = "res";
     }
 }
@@ -4970,39 +4963,29 @@ gen_function_decl_parameters (hsa_function_representation *f,
    result.  */
 
 static void
-gen_function_def_parameters (hsa_function_representation *f,
-			     vec <hsa_op_reg_p> *ssa_map)
+gen_function_def_parameters (vec <hsa_op_reg_p> *ssa_map)
 {
   tree parm;
-  int i, count = 0;
-
-  for (parm = DECL_ARGUMENTS (cfun->decl); parm; parm = DECL_CHAIN (parm))
-    count++;
-
-  f->m_input_args_count = count;
-
-  /* Allocate one more argument which can be potentially used for a kernel
-     dispatching.  */
-  f->m_input_args = XCNEWVEC (hsa_symbol, f->m_input_args_count + 1);
 
   hsa_bb *prologue = hsa_bb_for_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun));
 
-  for (parm = DECL_ARGUMENTS (cfun->decl), i = 0;
-       parm;
-       parm = DECL_CHAIN (parm), i++)
+  for (parm = DECL_ARGUMENTS (cfun->decl); parm;
+       parm = DECL_CHAIN (parm))
     {
       struct hsa_symbol **slot;
 
-      fillup_sym_for_decl (parm, &f->m_input_args[i]);
+      hsa_symbol *arg = new hsa_symbol
+	(BRIG_TYPE_NONE,
+	 hsa_cfun->m_kern_p ? BRIG_SEGMENT_KERNARG : BRIG_SEGMENT_ARG,
+	 BRIG_LINKAGE_FUNCTION);
+      arg->fillup_for_decl (parm);
+
+      hsa_cfun->m_input_args.safe_push (arg);
 
       if (hsa_seen_error ())
 	return;
 
-      f->m_input_args[i].m_segment = f->m_kern_p ? BRIG_SEGMENT_KERNARG :
-				       BRIG_SEGMENT_ARG;
-      f->m_input_args[i].m_linkage = BRIG_LINKAGE_FUNCTION;
-      f->m_input_args[i].m_name = hsa_get_declaration_name (parm);
-      hsa_symbol *arg = &f->m_input_args[i];
+      arg->m_name = hsa_get_declaration_name (parm);
 
       /* Copy all input arguments and create corresponding private symbols
 	 for them.  */
@@ -5013,9 +4996,7 @@ gen_function_def_parameters (hsa_function_representation *f,
 	  || (!is_gimple_reg (parm) && !TREE_READONLY (parm)))
 	{
 	  private_arg = hsa_cfun->create_hsa_temporary (arg->m_type);
-	  hsa_cfun->m_private_variables.safe_push (private_arg);
-	  fillup_sym_for_decl (parm, private_arg);
-	  f->m_private_variables.safe_push (private_arg);
+	  private_arg->fillup_for_decl (parm);
 
 	  hsa_op_address *private_arg_addr = new hsa_op_address (private_arg);
 	  gen_hsa_memory_copy (prologue, private_arg_addr, parm_addr,
@@ -5024,7 +5005,7 @@ gen_function_def_parameters (hsa_function_representation *f,
       else
 	private_arg = arg;
 
-      slot = f->m_local_symbols->find_slot (private_arg, INSERT);
+      slot = hsa_cfun->m_local_symbols->find_slot (private_arg, INSERT);
       gcc_assert (!*slot);
       *slot = private_arg;
 
@@ -5048,18 +5029,18 @@ gen_function_def_parameters (hsa_function_representation *f,
     {
       struct hsa_symbol **slot;
 
-      f->m_output_arg = XCNEW (hsa_symbol);
-      fillup_sym_for_decl (DECL_RESULT (cfun->decl), f->m_output_arg);
+      hsa_cfun->m_output_arg = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_ARG,
+					       BRIG_LINKAGE_FUNCTION);
+      hsa_cfun->m_output_arg->fillup_for_decl (DECL_RESULT (cfun->decl));
 
       if (hsa_seen_error ())
 	return;
 
-      f->m_output_arg->m_segment = BRIG_SEGMENT_ARG;
-      f->m_output_arg->m_linkage = BRIG_LINKAGE_FUNCTION;
-      f->m_output_arg->m_name = "res";
-      slot = f->m_local_symbols->find_slot (f->m_output_arg, INSERT);
+      hsa_cfun->m_output_arg->m_name = "res";
+      slot = hsa_cfun->m_local_symbols->find_slot (hsa_cfun->m_output_arg,
+						   INSERT);
       gcc_assert (!*slot);
-      *slot = f->m_output_arg;
+      *slot = hsa_cfun->m_output_arg;
     }
 }
 
@@ -5069,10 +5050,10 @@ gen_function_def_parameters (hsa_function_representation *f,
 hsa_function_representation *
 hsa_generate_function_declaration (tree decl)
 {
-  hsa_function_representation *fun = XCNEW (hsa_function_representation);
+  hsa_function_representation *fun = new hsa_function_representation
+    (decl, false);
 
   fun->m_declaration_p = true;
-  fun->m_decl = decl;
   fun->m_name = get_brig_function_name (decl);
   gen_function_decl_parameters (fun, decl);
 
@@ -5320,6 +5301,7 @@ convert_switch_statements ()
 
 	      gphi *phi = it.phi ();
 	      add_phi_arg (phi, phi_def->phi_value, new_edge, UNKNOWN_LOCATION);
+	      delete phi_def;
 	    }
 
 	/* Remove the original GIMPLE switch statement.  */
@@ -5360,13 +5342,14 @@ static void
 generate_hsa (bool kernel)
 {
   vec <hsa_op_reg_p> ssa_map = vNULL;
+  hsa_init_data_for_cfun ();
 
   if (hsa_num_threads == NULL)
     emit_hsa_module_variables ();
 
   /* Initialize hsa_cfun.  */
   hsa_cfun = new hsa_function_representation (cfun->decl, kernel);
-  hsa_init_data_for_cfun ();
+  hsa_cfun->init_extra_bbs ();
 
   if (flag_tm)
     {
@@ -5382,7 +5365,7 @@ generate_hsa (bool kernel)
   ssa_map.safe_grow_cleared (SSANAMES (cfun)->length ());
   hsa_cfun->m_name = get_brig_function_name (cfun->decl);
 
-  gen_function_def_parameters (hsa_cfun, &ssa_map);
+  gen_function_def_parameters (&ssa_map);
   if (hsa_seen_error ())
     goto fail;
 
@@ -5417,13 +5400,13 @@ generate_hsa (bool kernel)
 
 #endif
 
-  ssa_map.release ();
-
   hsa_regalloc ();
 
   hsa_brig_emit_function ();
 
  fail:
+  ssa_map.release ();
+
   hsa_deinit_data_for_cfun ();
 }
 
diff --git a/gcc/hsa.c b/gcc/hsa.c
index c4990e2..aca8bd4 100644
--- a/gcc/hsa.c
+++ b/gcc/hsa.c
@@ -131,7 +131,8 @@ hsa_init_compilation_unit_data (void)
     return;
 
   compilation_unit_data_initialized = true;
-  hsa_global_variable_symbols = new hash_table <hsa_free_symbol_hasher> (8);
+
+  hsa_failed_functions = new hash_set <tree> ();
 }
 
 /* Free data structures that are used when dealing with different
@@ -140,11 +141,11 @@ hsa_init_compilation_unit_data (void)
 void
 hsa_deinit_compilation_unit_data (void)
 {
-  if (compilation_unit_data_initialized)
-    delete hsa_global_variable_symbols;
-
   if (hsa_failed_functions)
     delete hsa_failed_functions;
+
+  if (hsa_num_threads)
+    delete hsa_num_threads;
 }
 
 /* Return true if we are generating large HSA machine model.  */
@@ -547,6 +548,17 @@ hsa_destroy_insn (hsa_insn_basic *insn)
       block->~hsa_insn_arg_block ();
       return;
     }
+  if (hsa_insn_sbr *sbr = dyn_cast <hsa_insn_sbr *> (insn))
+    {
+      sbr->~hsa_insn_sbr ();
+      return;
+    }
+  if (hsa_insn_comment *comment = dyn_cast <hsa_insn_comment *> (insn))
+    {
+      comment->~hsa_insn_comment ();
+      return;
+    }
+
   insn->~hsa_insn_basic ();
   return;
 }
@@ -711,8 +723,6 @@ hsa_seen_error (void)
 void
 hsa_fail_cfun (void)
 {
-  if (hsa_failed_functions == NULL)
-    hsa_failed_functions = new hash_set <tree> ();
   hsa_failed_functions->add (hsa_cfun->m_decl);
   hsa_cfun->m_seen_error = true;
 }
diff --git a/gcc/hsa.h b/gcc/hsa.h
index f4184f9..dfa0d1f 100644
--- a/gcc/hsa.h
+++ b/gcc/hsa.h
@@ -53,19 +53,18 @@ typedef hsa_insn_basic *hsa_insn_basic_p;
 
 struct hsa_symbol
 {
-  /* Default constructor.  */
-  hsa_symbol ();
-
   /* Constructor.  */
   hsa_symbol (BrigType16_t type, BrigSegment8_t segment,
 	      BrigLinkage8_t linkage);
 
-  /* New operator to allocate HSA symbol from pool alloc.  */
-  void *operator new (size_t);
-
   /* Return total size of the symbol.  */
   unsigned HOST_WIDE_INT total_byte_size ();
 
+  /* Fill in those values into the symbol according to DECL, which are
+     determined independently from whether it is parameter, result,
+     or a variable, local or global.  */
+  void fillup_for_decl (tree decl);
+
   /* Pointer to the original tree, which is PARM_DECL for input parameters and
      RESULT_DECL for the output parameters.  */
   tree m_decl;
@@ -102,6 +101,10 @@ struct hsa_symbol
 
   /* True if an error has been seen for the symbol.  */
   bool m_seen_error;
+
+private:
+  /* Default constructor.  */
+  hsa_symbol ();
 };
 
 /* Abstract class for HSA instruction operands. */
@@ -483,6 +486,9 @@ class hsa_insn_sbr : public hsa_insn_basic
 public:
   hsa_insn_sbr (hsa_op_reg *index, unsigned jump_count);
 
+  /* Default destructor.  */
+  ~hsa_insn_sbr ();
+
   void *operator new (size_t);
 
   void replace_all_labels (basic_block old_bb, basic_block new_bb);
@@ -708,6 +714,9 @@ class hsa_insn_call : public hsa_insn_basic
 public:
   hsa_insn_call (tree callee);
 
+  /* Default destructor.  */
+  ~hsa_insn_call ();
+
   void *operator new (size_t);
 
   /* Called function */
@@ -725,15 +734,9 @@ public:
   /* Called function code reference.  */
   hsa_op_code_ref m_func;
 
-  /* Argument symbols.  */
-  auto_vec <hsa_symbol *> m_args_symbols;
-
   /* Code list for arguments of the function.  */
   hsa_op_code_list *m_args_code_list;
 
-  /* Result symbol.  */
-  hsa_symbol *m_result_symbol;
-
   /* Code list for result of the function.  */
   hsa_op_code_list *m_result_code_list;
 private:
@@ -796,13 +799,10 @@ public:
   /* Constructor of class representing the comment in HSAIL.  */
   hsa_insn_comment (const char *s);
 
-  void *operator new (size_t);
-
-  /* Destructor.  */
+  /* Default destructor.  */
   ~hsa_insn_comment ();
 
-  /* Release memory for comment.  */
-  void release_string ();
+  void *operator new (size_t);
 
   char *m_comment;
 };
@@ -957,17 +957,15 @@ public:
   /* Name of the function.  */
   char *m_name;
 
-  /* Input arguments of the function.  */
-  /* FIXME: Normally we'd use a vector, however our C++ vectors seem to have
-     problems with derived classes, so for now we'll use a simple array.  */
-  unsigned m_input_args_count;
-
   /* Number of allocated register structures.  */
   int m_reg_count;
 
-  hsa_symbol *m_input_args;
+  /* Input arguments.  */
+  vec <hsa_symbol *> m_input_args;
+
   /* Output argument or NULL if there is none.  */
   hsa_symbol *m_output_arg;
+
   /* Hash table of local variable symbols.  */
   hash_table <hsa_noop_symbol_hasher> *m_local_symbols;
 
@@ -1080,7 +1078,6 @@ hsa_summary_t::link_functions (cgraph_node *gpu, cgraph_node *host,
 
 /* in hsa.c */
 extern struct hsa_function_representation *hsa_cfun;
-extern hash_table <hsa_free_symbol_hasher> *hsa_global_variable_symbols;
 extern hash_map <tree, vec <const char *> *> *hsa_decl_kernel_dependencies;
 extern hsa_summary_t *hsa_summaries;
 extern hsa_symbol *hsa_num_threads;
-- 
2.6.2

>From 0d38552c5c84e54aa7b1cf7d6fa38c80b85b6108 Mon Sep 17 00:00:00 2001
From: marxin <mliska@suse.cz>
Date: Tue, 27 Oct 2015 16:01:56 +0100
Subject: [PATCH 6/9] HSA: introduce hsa_debug_symbol and refact.
 hsa_function_representation.

gcc/ChangeLog:

2015-10-27  Martin Liska  <mliska@suse.cz>

	* hsa-dump.c (dump_hsa_symbol): New function.
	(debug_hsa_symbol): Likewise.
	* hsa-gen.c (hsa_function_representation::~hsa_function_representation):
	Release memory.
	(generate_hsa): Use hsa_cfun->m_map.
	* hsa.h: Declare hsa_function_representation::m_map.
---
 gcc/hsa-dump.c | 29 +++++++++++++++++++++++++++++
 gcc/hsa-gen.c  | 19 ++++++++-----------
 gcc/hsa.h      |  3 +++
 3 files changed, 40 insertions(+), 11 deletions(-)

diff --git a/gcc/hsa-dump.c b/gcc/hsa-dump.c
index 1a68bc2..6e58001 100644
--- a/gcc/hsa-dump.c
+++ b/gcc/hsa-dump.c
@@ -726,6 +726,26 @@ dump_hsa_address (FILE *f, hsa_op_address *addr)
     fprintf (f, "[" HOST_WIDE_INT_PRINT_DEC "]", addr->m_imm_offset);
 }
 
+/* Dump textual representation of HSA IL symbol SYMBOL to file F.  */
+
+static void
+dump_hsa_symbol (FILE *f, hsa_symbol *symbol)
+{
+  const char *name;
+  if (symbol->m_name)
+    name = symbol->m_name;
+  else
+    {
+      char buf[64];
+      sprintf (buf, "__%s_%i", hsa_seg_name (symbol->m_segment),
+	       symbol->m_name_number);
+
+      name = buf;
+    }
+
+  fprintf (f, "%s (%s)", name, hsa_type_name (symbol->m_type));
+}
+
 /* Dump textual representation of HSA IL operand OP to file F.  */
 
 static void
@@ -1127,3 +1147,12 @@ debug_hsa_operand (hsa_op_base *opc)
   dump_hsa_operand (stderr, opc, true);
   fprintf (stderr, "\n");
 }
+
+/* Dump textual representation of as HSA symbol.  */
+
+DEBUG_FUNCTION void
+debug_hsa_symbol (hsa_symbol *symbol)
+{
+  dump_hsa_symbol (stderr, symbol);
+  fprintf (stderr, "\n");
+}
diff --git a/gcc/hsa-gen.c b/gcc/hsa-gen.c
index 4a30eb0..2139499 100644
--- a/gcc/hsa-gen.c
+++ b/gcc/hsa-gen.c
@@ -262,7 +262,7 @@ hsa_function_representation::hsa_function_representation
   m_private_variables (vNULL), m_called_functions (vNULL), m_hbb_count (0),
   m_in_ssa (true), m_kern_p (kernel_p), m_declaration_p (false), m_decl (fdecl),
   m_shadow_reg (NULL), m_kernel_dispatch_count (0), m_maximum_omp_data_size (0),
-  m_seen_error (false), m_temp_symbol_count (0)
+  m_seen_error (false), m_temp_symbol_count (0), m_ssa_map ()
 {
   int sym_init_len = (vec_safe_length (cfun->local_decls) / 2) + 1;;
   m_local_symbols = new hash_table <hsa_noop_symbol_hasher> (sym_init_len);
@@ -296,6 +296,7 @@ hsa_function_representation::~hsa_function_representation ()
     delete m_private_variables[i];
   m_private_variables.release ();
   m_called_functions.release ();
+  m_ssa_map.release ();
 }
 
 hsa_op_reg *
@@ -5341,7 +5342,6 @@ emit_hsa_module_variables (void)
 static void
 generate_hsa (bool kernel)
 {
-  vec <hsa_op_reg_p> ssa_map = vNULL;
   hsa_init_data_for_cfun ();
 
   if (hsa_num_threads == NULL)
@@ -5349,6 +5349,7 @@ generate_hsa (bool kernel)
 
   /* Initialize hsa_cfun.  */
   hsa_cfun = new hsa_function_representation (cfun->decl, kernel);
+  hsa_cfun->m_ssa_map.safe_grow_cleared (SSANAMES (cfun)->length ());
   hsa_cfun->init_extra_bbs ();
 
   if (flag_tm)
@@ -5362,16 +5363,15 @@ generate_hsa (bool kernel)
   if (hsa_seen_error ())
     goto fail;
 
-  ssa_map.safe_grow_cleared (SSANAMES (cfun)->length ());
   hsa_cfun->m_name = get_brig_function_name (cfun->decl);
 
-  gen_function_def_parameters (&ssa_map);
+  gen_function_def_parameters (&hsa_cfun->m_ssa_map);
   if (hsa_seen_error ())
     goto fail;
 
   init_prologue ();
 
-  gen_body_from_gimple (&ssa_map);
+  gen_body_from_gimple (&hsa_cfun->m_ssa_map);
   if (hsa_seen_error ())
     goto fail;
 
@@ -5385,9 +5385,9 @@ generate_hsa (bool kernel)
     }
 
 #ifdef ENABLE_CHECKING
-  for (unsigned i = 0; i < ssa_map.length (); i++)
-    if (ssa_map[i])
-      ssa_map[i]->verify_ssa ();
+  for (unsigned i = 0; i < hsa_cfun->m_ssa_map.length (); i++)
+    if (hsa_cfun->m_ssa_map[i])
+      hsa_cfun->m_ssa_map[i]->verify_ssa ();
 
   basic_block bb;
   FOR_EACH_BB_FN (bb, cfun)
@@ -5401,12 +5401,9 @@ generate_hsa (bool kernel)
 #endif
 
   hsa_regalloc ();
-
   hsa_brig_emit_function ();
 
  fail:
-  ssa_map.release ();
-
   hsa_deinit_data_for_cfun ();
 }
 
diff --git a/gcc/hsa.h b/gcc/hsa.h
index dfa0d1f..0bdd530 100644
--- a/gcc/hsa.h
+++ b/gcc/hsa.h
@@ -1016,6 +1016,9 @@ public:
 
   /* Counter for temporary symbols created in the function representation.  */
   unsigned m_temp_symbol_count;
+
+  /* SSA names mapping.  */
+  vec <hsa_op_reg_p> m_ssa_map;
 };
 
 enum hsa_function_kind
-- 
2.6.2

>From 1aad365cac3f81561bf0c9f819a4f9515300f347 Mon Sep 17 00:00:00 2001
From: marxin <mliska@suse.cz>
Date: Fri, 30 Oct 2015 20:04:33 +0100
Subject: [PATCH 7/9] HSA: prepend _m to hsa_insn_basic::operands

gcc/ChangeLog:

2015-10-30  Martin Liska  <mliska@suse.cz>

	* hsa-gen.c (hsa_insn_basic::hsa_insn_basic): Rename operands
	to m_operands.
	(hsa_insn_basic::set_op): Likewise.
	(hsa_insn_basic::get_op): Likewise.
	(hsa_insn_basic::get_op_addr): Likewise.
	(hsa_insn_basic::operand_count): Likewise.
	* hsa.h: Likewise.
---
 gcc/hsa-gen.c | 12 ++++++------
 gcc/hsa.h     |  2 +-
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/gcc/hsa-gen.c b/gcc/hsa-gen.c
index 2139499..3a0b99b7 100644
--- a/gcc/hsa-gen.c
+++ b/gcc/hsa-gen.c
@@ -1155,7 +1155,7 @@ hsa_insn_basic::hsa_insn_basic (unsigned nops, int opc): m_prev (NULL),
   m_type (BRIG_TYPE_NONE), m_brig_offset (0)
 {
   if (nops > 0)
-    operands.safe_grow_cleared (nops);
+    m_operands.safe_grow_cleared (nops);
 
   hsa_instructions.safe_push (this);
 }
@@ -1184,7 +1184,7 @@ hsa_insn_basic::set_op (int index, hsa_op_base *op)
 	}
     }
 
-  operands[index] = op;
+  m_operands[index] = op;
 }
 
 /* Get INDEX-th operand of the instruction.  */
@@ -1192,7 +1192,7 @@ hsa_insn_basic::set_op (int index, hsa_op_base *op)
 hsa_op_base *
 hsa_insn_basic::get_op (int index)
 {
-  return operands[index];
+  return m_operands[index];
 }
 
 /* Get address of INDEX-th operand of the instruction.  */
@@ -1200,14 +1200,14 @@ hsa_insn_basic::get_op (int index)
 hsa_op_base **
 hsa_insn_basic::get_op_addr (int index)
 {
-  return &operands[index];
+  return &m_operands[index];
 }
 
 /* Get number of operands of the instruction.  */
 unsigned int
 hsa_insn_basic::operand_count ()
 {
-  return operands.length ();
+  return m_operands.length ();
 }
 
 /* Constructor of the class which is the bases of all instructions and directly
@@ -1222,7 +1222,7 @@ hsa_insn_basic::hsa_insn_basic (unsigned nops, int opc, BrigType16_t t,
   m_type (t),  m_brig_offset (0)
 {
   if (nops > 0)
-    operands.safe_grow_cleared (nops);
+    m_operands.safe_grow_cleared (nops);
 
   if (arg0 != NULL)
     {
diff --git a/gcc/hsa.h b/gcc/hsa.h
index 0bdd530..f08b12e 100644
--- a/gcc/hsa.h
+++ b/gcc/hsa.h
@@ -414,7 +414,7 @@ private:
      fewer instructions and so will fit the internal storage.  */
   /* TODO: Vast majority of instructions have three or fewer operands, so we
      may actually try reducing it.  */
-  auto_vec<hsa_op_base *, HSA_BRIG_INT_STORAGE_OPERANDS> operands;
+  auto_vec<hsa_op_base *, HSA_BRIG_INT_STORAGE_OPERANDS> m_operands;
 };
 
 /* Class representing a PHI node of the SSA form of HSA virtual
-- 
2.6.2

>From 77d7f6ee98a46fa123394a5073f44ae591e26c76 Mon Sep 17 00:00:00 2001
From: marxin <mliska@suse.cz>
Date: Tue, 27 Oct 2015 17:49:05 +0100
Subject: [PATCH 8/9] HSA: correctly handle memory order for atomic insns

gcc/ChangeLog:

2015-10-27  Martin Liska  <mliska@suse.cz>

	* hsa-gen.c (hsa_insn_signal::hsa_insn_signal): Use modified
	ctor of hsa_insn_atomic.
	(gen_hsa_insns_for_kernel_call): Likewise.
	(get_memory_order_name): New function.
	(get_memory_order): New function.
	(gen_hsa_ternary_atomic_for_builtin): Fill up memory order.
	(gen_hsa_insns_for_call): Likewise.
	* hsa.h: Declare new argument for
	hsa_insn_atomic::hsa_insn_atomic.
---
 gcc/hsa-gen.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++--------
 gcc/hsa.h     |   2 +-
 2 files changed, 108 insertions(+), 18 deletions(-)

diff --git a/gcc/hsa-gen.c b/gcc/hsa-gen.c
index 3a0b99b7..856fdce 100644
--- a/gcc/hsa-gen.c
+++ b/gcc/hsa-gen.c
@@ -1429,11 +1429,12 @@ hsa_insn_mem::operator new (size_t)
 
 hsa_insn_atomic::hsa_insn_atomic (int nops, int opc,
 				  enum BrigAtomicOperation aop,
-				  BrigType16_t t, hsa_op_base *arg0,
+				  BrigType16_t t, BrigMemoryOrder memorder,
+				  hsa_op_base *arg0,
 				  hsa_op_base *arg1, hsa_op_base *arg2,
 				  hsa_op_base *arg3)
   : hsa_insn_mem (nops, opc, t, arg0, arg1, arg2, arg3), m_atomicop (aop),
-  m_memoryorder (BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE),
+  m_memoryorder (memorder),
   m_memoryscope (BRIG_MEMORY_SCOPE_SYSTEM)
 {
   gcc_checking_assert (opc == BRIG_OPCODE_ATOMICNORET ||
@@ -1462,7 +1463,8 @@ hsa_insn_signal::hsa_insn_signal (int nops, int opc,
 				  BrigType16_t t, hsa_op_base *arg0,
 				  hsa_op_base *arg1, hsa_op_base *arg2,
 				  hsa_op_base *arg3)
-  : hsa_insn_atomic (nops, opc, sop, t, arg0, arg1, arg2, arg3)
+  : hsa_insn_atomic (nops, opc, sop, t, BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE,
+		     arg0, arg1, arg2, arg3)
 {
 }
 
@@ -4028,10 +4030,9 @@ gen_hsa_insns_for_kernel_call (hsa_bb *hbb, gcall *call)
   /* Store 5122 << 16 + 1 to packet->header.  */
   c = new hsa_op_immed (70658, BRIG_TYPE_U32);
 
-  hsa_insn_atomic *atomic = new hsa_insn_atomic (2, BRIG_OPCODE_ATOMICNORET,
-						 BRIG_ATOMIC_ST, BRIG_TYPE_B32,
-						 addr, c);
-  atomic->m_memoryorder = BRIG_MEMORY_ORDER_SC_RELEASE;
+  hsa_insn_atomic *atomic = new hsa_insn_atomic
+    (2, BRIG_OPCODE_ATOMICNORET, BRIG_ATOMIC_ST, BRIG_TYPE_B32,
+     BRIG_MEMORY_ORDER_SC_RELEASE, addr, c);
   atomic->m_memoryscope = BRIG_MEMORY_SCOPE_SYSTEM;
 
   hbb->append_insn (atomic);
@@ -4145,6 +4146,54 @@ get_address_from_value (tree val, hsa_bb *hbb, vec <hsa_op_reg_p> *ssa_map)
     }
 }
 
+/* Return strign for MEMMODEL.  */
+
+static const char *
+get_memory_order_name (unsigned memmodel)
+{
+  switch (memmodel)
+    {
+    case __ATOMIC_RELAXED:
+      return "__ATOMIC_RELAXED";
+    case __ATOMIC_CONSUME:
+      return "__ATOMIC_CONSUME";
+    case __ATOMIC_ACQUIRE:
+      return "__ATOMIC_ACQUIRE";
+    case __ATOMIC_RELEASE:
+      return "__ATOMIC_RELEASE";
+    case __ATOMIC_ACQ_REL:
+      return "__ATOMIC_ACQ_REL";
+    case __ATOMIC_SEQ_CST:
+      return "__ATOMIC_SEQ_CST";
+    default:
+      return NULL;
+    }
+}
+
+/* Return memory order according to predefined __atomic memory model
+   constants.  LOCATION is provided to locate the problemati statement.  */
+
+static BrigMemoryOrder
+get_memory_order (unsigned memmodel, location_t location)
+{
+  switch (memmodel)
+    {
+    case __ATOMIC_RELAXED:
+      return BRIG_MEMORY_ORDER_RELAXED;
+    case __ATOMIC_ACQUIRE:
+      return BRIG_MEMORY_ORDER_SC_ACQUIRE;
+    case __ATOMIC_RELEASE:
+      return BRIG_MEMORY_ORDER_SC_RELEASE;
+    case __ATOMIC_ACQ_REL:
+      return BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE;
+    default:
+      HSA_SORRY_ATV (location,
+		     "support for HSA does not implement memory model: %s",
+		     get_memory_order_name (memmodel));
+      return BRIG_MEMORY_ORDER_NONE;
+    }
+}
+
 /* Helper function to create an HSA atomic binary operation instruction out of
    calls to atomic builtins.  RET_ORIG is true if the built-in is the variant
    that return s the value before applying operation, and false if it should
@@ -4161,8 +4210,22 @@ gen_hsa_ternary_atomic_for_builtin (bool ret_orig,
   tree lhs = gimple_call_lhs (stmt);
 
   tree type = TREE_TYPE (gimple_call_arg (stmt, 1));
-  BrigType16_t hsa_type  = hsa_type_for_scalar_tree_type (type, false);
+  BrigType16_t hsa_type = hsa_type_for_scalar_tree_type (type, false);
   BrigType16_t mtype = mem_type_for_type (hsa_type);
+  tree model = gimple_call_arg (stmt, 2);
+
+  if (!tree_fits_uhwi_p (model))
+    {
+      HSA_SORRY_ATV
+	(gimple_location (stmt),
+	 "support for HSA does not implement memory model %E", model);
+      return;
+    }
+
+  unsigned HOST_WIDE_INT mmodel = tree_to_uhwi (model);
+
+  BrigMemoryOrder memorder = get_memory_order
+    (mmodel, gimple_location (stmt));
 
   /* Certain atomic insns must have Bx memory types.  */
   switch (acode)
@@ -4193,12 +4256,19 @@ gen_hsa_ternary_atomic_for_builtin (bool ret_orig,
       nops = 2;
     }
 
-  hsa_insn_atomic *atominsn = new hsa_insn_atomic (nops, opcode, acode, mtype);
-
   /* Overwrite default memory order for ATOMIC_ST insn which can have just
      RLX or SCREL memory order.  */
-  if (acode == BRIG_ATOMIC_ST)
-    atominsn->m_memoryorder = BRIG_MEMORY_ORDER_SC_RELEASE;
+  if (acode == BRIG_ATOMIC_ST && memorder != BRIG_MEMORY_ORDER_RELAXED
+      && memorder != BRIG_MEMORY_ORDER_SC_RELEASE)
+    {
+      HSA_SORRY_ATV (gimple_location (stmt),
+		     "support for HSA does not implement memory model for "
+		     "ATOMIC_ST: %s", get_memory_order_name (mmodel));
+      return;
+    }
+
+  hsa_insn_atomic *atominsn = new hsa_insn_atomic (nops, opcode, acode, mtype,
+						   memorder);
 
   hsa_op_address *addr;
   addr = get_address_from_value (gimple_call_arg (stmt, 0), hbb, ssa_map);
@@ -4369,6 +4439,28 @@ gen_hsa_insns_for_call (gimple *stmt, hsa_bb *hbb,
 	BrigType16_t mtype;
 	hsa_op_address *addr;
 	addr = get_address_from_value (gimple_call_arg (stmt, 0), hbb, ssa_map);
+	tree model = gimple_call_arg (stmt, 1);
+	if (!tree_fits_uhwi_p (model))
+	  {
+	    HSA_SORRY_ATV
+	      (gimple_location (stmt),
+	       "support for HSA does not implement memory model: %E", model);
+	    return;
+	  }
+
+	unsigned HOST_WIDE_INT mmodel = tree_to_uhwi (model);
+	BrigMemoryOrder memorder = get_memory_order (mmodel,
+						     gimple_location (stmt));
+
+	if (memorder != BRIG_MEMORY_ORDER_RELAXED
+	    && memorder != BRIG_MEMORY_ORDER_SC_RELEASE)
+	  {
+	    HSA_SORRY_ATV
+	      (gimple_location (stmt),
+	       "support for HSA does not implement memory model for "
+	       "ATOMIC_LD: %s", get_memory_order_name (mmodel));
+	    return;
+	  }
 
 	if (lhs)
 	  {
@@ -4385,9 +4477,7 @@ gen_hsa_insns_for_call (gimple *stmt, hsa_bb *hbb,
 
 	hsa_insn_atomic *atominsn
 	  = new hsa_insn_atomic (2, BRIG_OPCODE_ATOMIC, BRIG_ATOMIC_LD, mtype,
-				 dest, addr);
-
-	atominsn->m_memoryorder = BRIG_MEMORY_ORDER_SC_ACQUIRE;
+				 memorder, dest, addr);
 
 	hbb->append_insn (atominsn);
 	break;
@@ -4515,7 +4605,8 @@ gen_hsa_insns_for_call (gimple *stmt, hsa_bb *hbb,
 	  (hsa_type_for_scalar_tree_type (type, false));
 
 	hsa_insn_atomic *atominsn = new hsa_insn_atomic
-	  (4, BRIG_OPCODE_ATOMIC, BRIG_ATOMIC_CAS, atype);
+	  (4, BRIG_OPCODE_ATOMIC, BRIG_ATOMIC_CAS, atype,
+	   BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE);
 	hsa_op_address *addr;
 	addr = get_address_from_value (gimple_call_arg (stmt, 0), hbb, ssa_map);
 
@@ -4534,7 +4625,6 @@ gen_hsa_insns_for_call (gimple *stmt, hsa_bb *hbb,
 	atominsn->set_op
 	  (3, hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 2),
 					      hbb, ssa_map));
-	atominsn->m_memoryorder = BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE;
 
 	hbb->append_insn (atominsn);
 	break;
diff --git a/gcc/hsa.h b/gcc/hsa.h
index f08b12e..1081fb6 100644
--- a/gcc/hsa.h
+++ b/gcc/hsa.h
@@ -612,7 +612,7 @@ class hsa_insn_atomic : public hsa_insn_mem
 {
 public:
   hsa_insn_atomic (int nops, int opc, enum BrigAtomicOperation aop,
-		   BrigType16_t t,
+		   BrigType16_t t, BrigMemoryOrder memorder,
 		   hsa_op_base *arg0 = NULL, hsa_op_base *arg1 = NULL,
 		   hsa_op_base *arg2 = NULL, hsa_op_base *arg3 = NULL);
   void *operator new (size_t);
-- 
2.6.2


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]