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] HSA: add support for function declaration emission and, fix RA.


Hello.

Following patch implements emission of function declarations and removes hsa_call_block_insn.
The insn is replaced with a new hsa_arg_block_insn, which will make insn iteration flat and
much easier for register allocator.

Thanks,
Martin
>From abb5eb3cf4f8569d2e003aabc5f078fcd17348a6 Mon Sep 17 00:00:00 2001
From: mliska <mliska@suse.cz>
Date: Mon, 22 Jun 2015 17:51:11 +0200
Subject: [PATCH 1/2] HSA: add support for function declaration emission and
 fix RA.

gcc/ChangeLog:

2015-06-23  Martin Liska  <mliska@suse.cz>

	* hsa-brig.c (emit_directive_variable): Remove assert that
	is no longer valid.
	(emit_function_directives): Change the function that it accepts
	a hsa_function_representation and is used both for definitions and
	declarations.
	(emit_function_declaration): New function.
	(emit_arg_block): Remove.
	(emit_arg_block_insn): New function.
	(emit_insn): Add support for newly added hsa_insn_arg_block
	insn.
	(emit_call_insn): Use offsets of called functions because
	these function declaration are already emitted.
	(hsa_brig_emit_function): Emit function declarations for all called
	functions that haven't been seen yet.
	(hsa_output_brig): Do not process pseudo-linkage.
	* hsa-dump.c (dump_hsa_insn): Change argument type.
	(dump_hsa_bb): Fix indentation for hsa_arg_block_insn.
	* hsa-gen.c (hsa_deinit_data_for_cfun): Use newly added function
	release.
	(hsa_function_representation::hsa_function_representation): Add
	construction for newly added members.
	(hsa_function_representation::~hsa_function_representation): Add
	destruction for newly added members.
	(hsa_insn_arg_block::hsa_insn_arg_block): New function.
	(hsa_insn_arg_block::operator new): New function.
	(get_symbol_for_decl): Use new function.
	(gen_hsa_insns_for_direct_call): Save all called functions.
	(gen_hsa_insns_for_known_library_call): Use newly added function
	get_declaration_name.
	(get_function_arg_count): New.
	(gen_function_decl_parameters): Likewise.
	(gen_function_def_parameters): Add an optional argument and rename
	from:
	(gen_function_parameters): Removed.
	(hsa_generate_function_declaration): New.
	(generate_hsa): Fill up declaration for a hsa_function_representation.
	(hsa_init_data_for_cfun): Replace hsa_insn_call_block with hsa_insn_arg_block
	as template argument.
	* hsa-regalloc.c (naive_process_phi): Add assert.
	(hsa_num_def_ops): Change # of operands for call insn.
	(visit_insn): Remove.
	(remove_def_in_insn): Likewise.
	(merge_live_range_for_insn): Likewise.
	(linear_scan_regalloc): Simplify.
	* hsa.c	(get_declaration_name): New function.
	(hsa_free_decl_kernel_mapping): Add guard.
	* hsa.h (struct hsa_function_representation): Add new struct fields.
	(hsa_function_representation::release): New.

Fix call_block_insn and fix RA.

Fix RA and related stuff.
---
 gcc/hsa-brig.c     | 240 ++++++++++++++++++++++++++---------------------------
 gcc/hsa-dump.c     |  41 ++++-----
 gcc/hsa-gen.c      | 224 ++++++++++++++++++++++++++++++++-----------------
 gcc/hsa-regalloc.c | 136 +++++++++---------------------
 gcc/hsa.c          |  20 ++++-
 gcc/hsa.h          |  45 ++++++----
 6 files changed, 372 insertions(+), 334 deletions(-)

diff --git a/gcc/hsa-brig.c b/gcc/hsa-brig.c
index d06fe42..ff697ee 100644
--- a/gcc/hsa-brig.c
+++ b/gcc/hsa-brig.c
@@ -128,10 +128,6 @@ struct function_linkage_pair
   unsigned int offset;
 };
 
-/* Vector of function calls where we need to resolve function offsets.  */
-
-static auto_vec <function_linkage_pair> function_call_linkage;
-
 /* Add a new chunk, allocate data for it and initialize it.  */
 
 void
@@ -511,7 +507,6 @@ emit_directive_variable (struct hsa_symbol *symbol)
   dirvar.type = htole16 (symbol->type);
   dirvar.segment = symbol->segment;
   dirvar.align = get_alignment (dirvar.type);
-  gcc_assert (symbol->linkage);
   dirvar.linkage = symbol->linkage;
   dirvar.dim.lo = (uint32_t) symbol->dim;
   dirvar.dim.hi = (uint32_t) ((unsigned long long) symbol->dim >> 32);
@@ -522,11 +517,11 @@ emit_directive_variable (struct hsa_symbol *symbol)
   return symbol->directive_offset;
 }
 
-/* Emit directives describing the function, for example its input and output
-   arguments, local variables etc.  */
+/* Emit directives describing either a function declaration or
+   definition F.  */
 
 static BrigDirectiveExecutable *
-emit_function_directives (void)
+emit_function_directives (hsa_function_representation *f)
 {
   struct BrigDirectiveExecutable fndir;
   unsigned name_offset, inarg_off, scoped_off, next_toplev_off;
@@ -534,38 +529,43 @@ emit_function_directives (void)
   BrigDirectiveExecutable *ptr_to_fndir;
   hsa_symbol *sym;
 
-  name_offset = brig_emit_string (hsa_cfun->name, '&');
+  name_offset = brig_emit_string (f->name, '&');
   inarg_off = brig_code.total_size + sizeof(fndir)
-    + (hsa_cfun->output_arg ? sizeof (struct BrigDirectiveVariable) : 0);
+    + (f->output_arg ? sizeof (struct BrigDirectiveVariable) : 0);
   scoped_off = inarg_off
-    + hsa_cfun->input_args_count * sizeof (struct BrigDirectiveVariable);
-  for (hash_table <hsa_noop_symbol_hasher>::iterator iter
-	 = hsa_cfun->local_symbols->begin ();
-       iter != hsa_cfun->local_symbols->end ();
-       ++iter)
-    if (TREE_CODE ((*iter)->decl) == VAR_DECL)
-      count++;
-  count += hsa_cfun->spill_symbols.length ();
+    + f->input_args_count * sizeof (struct BrigDirectiveVariable);
+
+  if (!f->declaration_p)
+    {
+      for (hash_table <hsa_noop_symbol_hasher>::iterator iter
+	     = f->local_symbols->begin ();
+	   iter != f->local_symbols->end ();
+	   ++iter)
+	if (TREE_CODE ((*iter)->decl) == VAR_DECL)
+	  count++;
+      count += f->spill_symbols.length ();
+    }
 
   next_toplev_off = scoped_off + count * sizeof (struct BrigDirectiveVariable);
 
   memset (&fndir, 0, sizeof (fndir));
   fndir.base.byteCount = htole16 (sizeof (fndir));
-  fndir.base.kind = htole16 (hsa_cfun->kern_p ? BRIG_KIND_DIRECTIVE_KERNEL
+  fndir.base.kind = htole16 (f->kern_p ? BRIG_KIND_DIRECTIVE_KERNEL
 			     : BRIG_KIND_DIRECTIVE_FUNCTION);
   fndir.name = htole32 (name_offset);
-  fndir.inArgCount = htole16 (hsa_cfun->input_args_count);
-  fndir.outArgCount = htole16 (hsa_cfun->output_arg ? 1 : 0);
+  fndir.inArgCount = htole16 (f->input_args_count);
+  fndir.outArgCount = htole16 (f->output_arg ? 1 : 0);
   fndir.firstInArg = htole32 (inarg_off);
   fndir.firstCodeBlockEntry = htole32 (scoped_off);
   fndir.nextModuleEntry = htole32 (next_toplev_off);
-  fndir.linkage = BRIG_LINKAGE_PROGRAM;
-  fndir.modifier.allBits |= BRIG_EXECUTABLE_DEFINITION;
+  fndir.linkage = f->kern_p || TREE_PUBLIC (f->decl) ? BRIG_LINKAGE_PROGRAM :
+    BRIG_LINKAGE_MODULE;
+
+  if (!f->declaration_p)
+    fndir.modifier.allBits |= BRIG_EXECUTABLE_DEFINITION;
   memset (&fndir.reserved, 0, sizeof (fndir.reserved));
 
-  if (!function_offsets)
-    function_offsets = new hash_map<tree, BrigCodeOffset32_t> ();
-  function_offsets->put (cfun->decl, brig_code.total_size);
+  function_offsets->put (f->decl, brig_code.total_size);
 
   brig_code.add (&fndir, sizeof (fndir));
   /* XXX terrible hack: we need to set instCount after we emit all
@@ -579,23 +579,27 @@ emit_function_directives (void)
                                     + brig_code.cur_chunk->size
                                     - sizeof (fndir));
 
-  if (hsa_cfun->output_arg)
-    emit_directive_variable(hsa_cfun->output_arg);
-  for (int i = 0; i < hsa_cfun->input_args_count; i++)
-    emit_directive_variable(&hsa_cfun->input_args[i]);
-  for (hash_table <hsa_noop_symbol_hasher>::iterator iter
-	 = hsa_cfun->local_symbols->begin ();
-       iter != hsa_cfun->local_symbols->end ();
-       ++iter)
-    {
-      if (TREE_CODE ((*iter)->decl) == VAR_DECL)
-	brig_insn_count++;
-      emit_directive_variable(*iter);
-    }
-  for (int i = 0; hsa_cfun->spill_symbols.iterate (i, &sym); i++)
+  if (f->output_arg)
+    emit_directive_variable (f->output_arg);
+  for (unsigned i = 0; i < f->input_args_count; i++)
+    emit_directive_variable (&f->input_args[i]);
+
+  if (!f->declaration_p)
     {
-      emit_directive_variable (sym);
-      brig_insn_count++;
+      for (hash_table <hsa_noop_symbol_hasher>::iterator iter
+	     = f->local_symbols->begin ();
+	   iter != f->local_symbols->end ();
+	   ++iter)
+	{
+	  if (TREE_CODE ((*iter)->decl) == VAR_DECL)
+	    brig_insn_count++;
+	  emit_directive_variable (*iter);
+	}
+      for (int i = 0; f->spill_symbols.iterate (i, &sym); i++)
+	{
+	  emit_directive_variable (sym);
+	  brig_insn_count++;
+	}
     }
 
   return ptr_to_fndir;
@@ -1003,6 +1007,19 @@ emit_queued_operands (void)
     }
 }
 
+/* Emit directives describing the function that is used for
+a function declaration.  */
+static void
+emit_function_declaration (tree decl)
+{
+  hsa_function_representation *f = hsa_generate_function_declaration (decl);
+
+  emit_function_directives (f);
+  emit_queued_operands ();
+
+  delete f;
+}
+
 /* Emit an HSA memory instruction and all necessary directives, schedule
    necessary operands for writing .  */
 
@@ -1299,29 +1316,6 @@ emit_cvt_insn (hsa_insn_basic *insn)
   brig_insn_count++;
 }
 
-/* Emit arg block to code segment.  */
-
-static void
-emit_arg_block (bool is_start)
-{
-  if (is_start)
-    {
-      struct BrigDirectiveArgBlockStart repr;
-      repr.base.byteCount = htole16 (sizeof (repr));
-      repr.base.kind = htole16 (BRIG_KIND_DIRECTIVE_ARG_BLOCK_START);
-      brig_code.add (&repr, sizeof (repr));
-      brig_insn_count++;
-    }
-  else
-    {
-      struct BrigDirectiveArgBlockEnd repr;
-      repr.base.byteCount = htole16 (sizeof (repr));
-      repr.base.kind = htole16 (BRIG_KIND_DIRECTIVE_ARG_BLOCK_END);
-      brig_code.add (&repr, sizeof (repr));
-      brig_insn_count++;
-    }
-}
-
 /* Emit call instruction INSN, where this instruction must be closed
    within a call block instruction.  */
 
@@ -1343,13 +1337,12 @@ emit_call_insn (hsa_insn_basic *insn)
   operand_offsets[0] = htole32 (enqueue_op (call->result_code_list));
 
   /* Operand 1: func */
-  /* XXX: we have to save offset to operand section and
-     called function offset is filled up after all functions are visited. */
+  BrigCodeOffset32_t *func_offset = function_offsets->get
+    (call->called_function);
+  gcc_assert (func_offset != NULL);
+  call->func.directive_offset = *func_offset;
   unsigned int offset = enqueue_op (&call->func);
 
-  function_call_linkage.safe_push
-    (function_linkage_pair (call->called_function, offset));
-
   operand_offsets[1] = htole32 (offset);
   /* Operand 2: in-args.  */
   operand_offsets[2] = htole32 (enqueue_op (call->args_code_list));
@@ -1366,40 +1359,49 @@ emit_call_insn (hsa_insn_basic *insn)
   brig_insn_count++;
 }
 
-/* Emit call block instruction. This super instruction encapsulate all
-   instructions needed for argument load/store and corresponding
-   instruction.  */
+/* Emit argument block directive.  */
 
 static void
-emit_call_block_insn (hsa_insn_call_block *insn)
+emit_arg_block_insn (hsa_insn_arg_block *insn)
 {
-  /* Argument scope start.  */
-  emit_arg_block (true);
-
-  for (unsigned i = 0; i < insn->input_args.length (); i++)
+  switch (insn->kind)
     {
-      insn->call_insn->args_code_list->offsets[i] = htole32
-	(emit_directive_variable (insn->input_args[i]));
-      brig_insn_count++;
-    }
+    case BRIG_KIND_DIRECTIVE_ARG_BLOCK_START:
+      {
+	struct BrigDirectiveArgBlockStart repr;
+	repr.base.byteCount = htole16 (sizeof (repr));
+	repr.base.kind = htole16 (insn->kind);
+	brig_code.add (&repr, sizeof (repr));
+
+	for (unsigned i = 0; i < insn->call_insn->input_args.length (); i++)
+	  {
+	    insn->call_insn->args_code_list->offsets[i] = htole32
+	      (emit_directive_variable (insn->call_insn->input_args[i]));
+	    brig_insn_count++;
+	  }
+
+	if (insn->call_insn->result_symbol)
+	  {
+	    insn->call_insn->result_code_list->offsets[0] = htole32
+	      (emit_directive_variable (insn->call_insn->output_arg));
+	    brig_insn_count++;
+	  }
 
-  if (insn->call_insn->result_symbol)
-    {
-      insn->call_insn->result_code_list->offsets[0] = htole32
-	(emit_directive_variable (insn->output_arg));
-      brig_insn_count++;
+	break;
+      }
+    case BRIG_KIND_DIRECTIVE_ARG_BLOCK_END:
+      {
+	struct BrigDirectiveArgBlockEnd repr;
+	repr.base.byteCount = htole16 (sizeof (repr));
+	repr.base.kind = htole16 (insn->kind);
+	brig_code.add (&repr, sizeof (repr));
+	break;
+      }
+    default:
+      gcc_unreachable ();
     }
 
-  for (unsigned i = 0; i < insn->input_arg_insns.length (); i++)
-    emit_memory_insn (insn->input_arg_insns[i]);
-
-  emit_call_insn (insn->call_insn);
-
-  if (insn->output_arg_insn)
-    emit_memory_insn (insn->output_arg_insn);
-
-  /* Argument scope end.  */
-  emit_arg_block (false);
+  brig_insn_count++;
 }
 
 /* Emit a basic HSA instruction and all necessary directives, schedule
@@ -1512,9 +1514,9 @@ emit_insn (hsa_insn_basic *insn)
       emit_branch_insn (br);
       return;
     }
-  if (hsa_insn_call_block *call_block = dyn_cast <hsa_insn_call_block *> (insn))
+  if (hsa_insn_arg_block *arg_block = dyn_cast <hsa_insn_arg_block *> (insn))
     {
-      emit_call_block_insn (call_block);
+      emit_arg_block_insn (arg_block);
       return;
     }
   if (hsa_insn_call *call = dyn_cast <hsa_insn_call *> (insn))
@@ -1589,7 +1591,21 @@ hsa_brig_emit_function (void)
   memset (&op_queue, 0, sizeof (op_queue));
   op_queue.projected_size = brig_operand.total_size;
 
-  ptr_to_fndir = emit_function_directives ();
+  if (!function_offsets)
+    function_offsets = new hash_map<tree, BrigCodeOffset32_t> ();
+
+  for (unsigned i = 0; i < hsa_cfun->called_functions.length (); i++)
+    {
+      tree called = hsa_cfun->called_functions[i];
+
+      if (function_offsets->get (called) == NULL)
+	{
+	  emit_function_declaration (called);
+	  gcc_assert (function_offsets->get (called) != NULL);
+	}
+    }
+
+  ptr_to_fndir = emit_function_directives (hsa_cfun);
   for (insn = hsa_bb_for_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun))->first_insn;
        insn;
        insn = insn->next)
@@ -1803,30 +1819,6 @@ hsa_output_brig (void)
   if (!brig_initialized)
     return;
 
-  for (unsigned i = 0; i < function_call_linkage.length (); i++)
-    {
-      function_linkage_pair p = function_call_linkage[i];
-
-      if (!function_offsets)
-	{
-	  sorry ("Missing offset to a HSA function in call instruction");
-	  return;
-	}
-      BrigCodeOffset32_t *func_offset = function_offsets->get (p.function_decl);
-      if (*func_offset)
-        {
-	  BrigOperandCodeRef *code_ref = (BrigOperandCodeRef *)
-	    (brig_operand.get_ptr_by_offset (p.offset));
-	  gcc_assert (code_ref->base.kind == BRIG_KIND_OPERAND_CODE_REF);
-	  code_ref->ref = htole32 (*func_offset);
-	}
-      else
-	{
-	  sorry ("Missing offset to a HSA function in call instruction");
-	  return;
-	}
-    }
-
   saved_section = in_section;
 
   switch_to_section (get_section (BRIG_ELF_SECTION_NAME, SECTION_NOTYPE, NULL));
diff --git a/gcc/hsa-dump.c b/gcc/hsa-dump.c
index 2519765..e1adcbc 100644
--- a/gcc/hsa-dump.c
+++ b/gcc/hsa-dump.c
@@ -706,10 +706,10 @@ static void indent_stream (FILE *f, int indent)
 /* Dump textual representation of HSA IL instruction INSN to file F.  */
 
 static void
-dump_hsa_insn (FILE *f, hsa_insn_basic *insn, int indent)
+dump_hsa_insn (FILE *f, hsa_insn_basic *insn, int *indent)
 {
   gcc_checking_assert (insn);
-  indent_stream (f, indent);
+  indent_stream (f, *indent);
 
   if (insn->number)
     fprintf (f, "%5d: ", insn->number);
@@ -849,37 +849,38 @@ dump_hsa_insn (FILE *f, hsa_insn_basic *insn, int indent)
 	  }
       fprintf (f, "BB %i\n", hsa_bb_for_bb (target)->index);
     }
-  else if (is_a <hsa_insn_call_block *> (insn))
+  else if (is_a <hsa_insn_arg_block *> (insn))
     {
-      hsa_insn_call_block *call_block = as_a <hsa_insn_call_block *> (insn);
+      hsa_insn_arg_block *arg_block = as_a <hsa_insn_arg_block *> (insn);
+      bool start_p = arg_block->kind == BRIG_KIND_DIRECTIVE_ARG_BLOCK_START;
+      char c = start_p ? '{' : '}';
 
-      fprintf (f, "{\n");
-
-      for (unsigned i = 0; i < call_block->input_arg_insns.length (); i++)
-	dump_hsa_insn (f, call_block->input_arg_insns[i], indent + 2);
-
-      dump_hsa_insn (f, call_block->call_insn, indent + 2);
+      if (start_p)
+	{
+	  *indent += 2;
+	  indent_stream (f, 2);
+	}
 
-      if (call_block->output_arg_insn)
-	dump_hsa_insn (f, call_block->output_arg_insn, indent + 2);
+      if (!start_p)
+	*indent -= 2;
 
-      indent_stream (f, indent);
-      fprintf (f, "}\n");
+      fprintf (f, "%c\n", c);
     }
   else if (is_a <hsa_insn_call *> (insn))
     {
       hsa_insn_call *call = as_a <hsa_insn_call *> (insn);
-      const char *name = xstrdup (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (call->called_function)));
+      const char *name = get_declaration_name (call->called_function);
 
       fprintf (f, "call &%s", name);
 
       if (call->result_symbol)
-	fprintf (f, "(%%%s) ", call->result_symbol->name);
+	fprintf (f, "(%%res) ");
 
       fprintf (f, "(");
       for (unsigned i = 0; i < call->args_symbols.length (); i++)
         {
-	  fprintf (f, "%%%s", call->args_symbols[i]->name);
+	  fprintf (f, "%%__arg_%u", i);
+
 	  if (i != call->args_symbols.length () - 1)
 	    fprintf (f, ", ");
 	}
@@ -929,10 +930,12 @@ dump_hsa_bb (FILE *f, hsa_bb *hbb)
   /* FIXME: Dump a label or something instead.  */
   fprintf (f, "BB %i:\n", hbb->index);
 
+  int indent = 2;
   for (insn = hbb->first_phi; insn; insn = insn->next)
-    dump_hsa_insn (f, insn, 2);
+    dump_hsa_insn (f, insn, &indent);
+
   for (insn = hbb->first_insn; insn; insn = insn->next)
-    dump_hsa_insn (f, insn, 2);
+    dump_hsa_insn (f, insn, &indent);
 
   FOR_EACH_EDGE (e, ei, hbb->bb->succs)
     if (e->flags & EDGE_TRUE_VALUE)
diff --git a/gcc/hsa-gen.c b/gcc/hsa-gen.c
index fab0191..bd75cf0 100644
--- a/gcc/hsa-gen.c
+++ b/gcc/hsa-gen.c
@@ -86,7 +86,7 @@ static pool_allocator<hsa_insn_seg> *hsa_allocp_inst_seg;
 static pool_allocator<hsa_insn_cmp> *hsa_allocp_inst_cmp;
 static pool_allocator<hsa_insn_br> *hsa_allocp_inst_br;
 static pool_allocator<hsa_insn_call> *hsa_allocp_inst_call;
-static pool_allocator<hsa_insn_call_block> *hsa_allocp_inst_call_block;
+static pool_allocator<hsa_insn_arg_block> *hsa_allocp_inst_arg_block;
 static pool_allocator<hsa_bb> *hsa_allocp_bb;
 static pool_allocator<hsa_symbol> *hsa_allocp_symbols;
 
@@ -115,6 +115,8 @@ hsa_function_representation::hsa_function_representation ()
   hbb_count = 1;        /* 0 is for prologue.  */
   in_ssa = true;	/* We start in SSA.  */
   kern_p = false;
+  declaration_p = false;
+  called_functions = vNULL;
 }
 
 /* Destructor of class holding function/kernel-wide informaton and state.  */
@@ -129,6 +131,7 @@ hsa_function_representation::~hsa_function_representation ()
   if (!kern_p)
     free (name);
   spill_symbols.release ();
+  called_functions.release ();
 }
 
 /* Allocate HSA structures that we need only while generating with this.  */
@@ -164,8 +167,8 @@ hsa_init_data_for_cfun ()
     = new pool_allocator<hsa_insn_br> ("HSA branching instructions", 16);
   hsa_allocp_inst_call
     = new pool_allocator<hsa_insn_call> ("HSA call instructions", 16);
-  hsa_allocp_inst_call_block
-    = new pool_allocator<hsa_insn_call_block> ("HSA call block instructions",
+  hsa_allocp_inst_arg_block
+    = new pool_allocator<hsa_insn_arg_block> ("HSA arg block instructions",
 					       16);
   hsa_allocp_bb = new pool_allocator<hsa_bb> ("HSA basic blocks", 8);
 
@@ -220,10 +223,9 @@ hsa_deinit_data_for_cfun (void)
   delete hsa_allocp_inst_cmp;
   delete hsa_allocp_inst_br;
   delete hsa_allocp_inst_call;
-  delete hsa_allocp_inst_call_block;
+  delete hsa_allocp_inst_arg_block;
   delete hsa_allocp_bb;
   delete hsa_allocp_symbols;
-
   delete hsa_cfun;
 }
 
@@ -528,10 +530,7 @@ get_symbol_for_decl (tree decl)
     }
 
   fillup_sym_for_decl (decl, sym);
-  if (!DECL_NAME (decl))
-    sorry ("Support for HSA does not implement anonymous declarations");
-  else
-    sym->name = IDENTIFIER_POINTER (DECL_NAME (decl));
+  sym->name = get_declaration_name (decl);
   *slot = sym;
   return sym;
 }
@@ -682,17 +681,17 @@ hsa_op_code_list::operator new (size_t)
 /* Lookup or create a HSA pseudo register for a given gimple SSA name.  */
 
 static hsa_op_reg *
-hsa_reg_for_gimple_ssa (tree ssa, vec <hsa_op_reg_p> ssa_map)
+hsa_reg_for_gimple_ssa (tree ssa, vec <hsa_op_reg_p> *ssa_map)
 {
   hsa_op_reg *hreg;
 
   gcc_checking_assert (TREE_CODE (ssa) == SSA_NAME);
-  if (ssa_map[SSA_NAME_VERSION (ssa)])
-    return ssa_map[SSA_NAME_VERSION (ssa)];
+  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), true));
   hreg->gimple_ssa = ssa;
-  ssa_map[SSA_NAME_VERSION (ssa)] = hreg;
+  (*ssa_map)[SSA_NAME_VERSION (ssa)] = hreg;
 
   return hreg;
 }
@@ -902,21 +901,20 @@ hsa_insn_call::operator new (size_t)
   return hsa_allocp_inst_call->allocate ();
 }
 
-/* Constructor of class representing the block required to invoke a call in
-   HSAIL.  */
-hsa_insn_call_block::hsa_insn_call_block ()
-  : hsa_insn_basic (0, HSA_OPCODE_CALL_BLOCK)
+/* 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,
+					hsa_insn_call * call)
+  : hsa_insn_basic (0, HSA_OPCODE_ARG_BLOCK), kind (brig_kind),
+  call_insn (call)
 {
-  output_arg = NULL;
-  output_arg_insn = NULL;
-  call_insn = NULL;
 }
 
-/* New operator for classes representing HSAIL call blocks.  */
+/* New operator for classes representing HSAIL argument blocks.  */
 void *
-hsa_insn_call_block::operator new (size_t)
+hsa_insn_arg_block::operator new (size_t)
 {
-  return hsa_allocp_inst_call_block->allocate ();
+  return hsa_allocp_inst_arg_block->allocate ();
 }
 
 /* Append HSA instruction INSN to basic block HBB.  */
@@ -977,7 +975,7 @@ hsa_append_insn_after (hsa_insn_basic *new_insn, hsa_insn_basic *old_insn)
    SSA names to HSA registers.  Append an new conversion statements to HBB.  */
 
 static hsa_op_reg *
-hsa_reg_for_gimple_ssa_reqtype (tree ssa, vec <hsa_op_reg_p> ssa_map,
+hsa_reg_for_gimple_ssa_reqtype (tree ssa, vec <hsa_op_reg_p> *ssa_map,
 				hsa_bb *hbb, BrigType16_t reqtype)
 {
   hsa_op_reg *reg = hsa_reg_for_gimple_ssa (ssa, ssa_map);
@@ -1004,7 +1002,7 @@ hsa_reg_for_gimple_ssa_reqtype (tree ssa, vec <hsa_op_reg_p> ssa_map,
    uses.  */
 
 static hsa_op_with_type *
-gen_address_calculation (tree exp, hsa_bb *hbb, vec <hsa_op_reg_p> ssa_map,
+gen_address_calculation (tree exp, hsa_bb *hbb, vec <hsa_op_reg_p> *ssa_map,
 			 BrigType16_t addrtype, hsa_insn_basic *new_use)
 {
   int opcode;
@@ -1095,7 +1093,7 @@ add_addr_regs_if_needed (hsa_op_reg *r1, hsa_op_reg *r2, hsa_bb *hbb)
 static void
 process_mem_base (tree base, hsa_symbol **symbol, BrigType16_t *addrtype,
 		  hsa_op_reg **reg, offset_int *offset, hsa_bb *hbb,
-		  vec <hsa_op_reg_p> ssa_map)
+		  vec <hsa_op_reg_p> *ssa_map)
 {
   if (TREE_CODE (base) == SSA_NAME)
     {
@@ -1123,7 +1121,7 @@ process_mem_base (tree base, hsa_symbol **symbol, BrigType16_t *addrtype,
    pseudo-registers.  */
 
 static hsa_op_address *
-gen_hsa_addr (tree ref, hsa_bb *hbb, vec <hsa_op_reg_p> ssa_map)
+gen_hsa_addr (tree ref, hsa_bb *hbb, vec <hsa_op_reg_p> *ssa_map)
 {
   hsa_symbol *symbol = NULL;
   hsa_op_reg *reg = NULL;
@@ -1298,7 +1296,7 @@ gen_hsa_addr_for_arg (tree tree_type, int index)
 
 static void
 gen_hsa_addr_insns (tree val, hsa_op_reg *dest, hsa_bb *hbb,
-		    vec <hsa_op_reg_p> ssa_map)
+		    vec <hsa_op_reg_p> *ssa_map)
 {
   hsa_op_address *addr;
   hsa_insn_basic *insn = new hsa_insn_basic (2, BRIG_OPCODE_LDA);
@@ -1347,7 +1345,7 @@ gen_hsa_addr_insns (tree val, hsa_op_reg *dest, hsa_bb *hbb,
 
 static hsa_op_with_type *
 hsa_reg_or_immed_for_gimple_op (tree op, hsa_bb *hbb,
-				vec <hsa_op_reg_p> ssa_map,
+				vec <hsa_op_reg_p> *ssa_map,
 				hsa_insn_basic *new_use)
 {
   hsa_op_reg *tmp;
@@ -1394,7 +1392,7 @@ hsa_build_append_simple_mov (hsa_op_reg *dest, hsa_op_base *src, hsa_bb *hbb)
 
 static void
 gen_hsa_insns_for_load (hsa_op_reg *dest, tree rhs, tree type, hsa_bb *hbb,
-			vec <hsa_op_reg_p> ssa_map)
+			vec <hsa_op_reg_p> *ssa_map)
 {
   /* The destination SSA name will give us the type.  */
   if (TREE_CODE (rhs) == VIEW_CONVERT_EXPR)
@@ -1453,7 +1451,7 @@ gen_hsa_insns_for_load (hsa_op_reg *dest, tree rhs, tree type, hsa_bb *hbb,
 
 static void
 gen_hsa_insns_for_store (tree lhs, hsa_op_base *src, hsa_bb *hbb,
-			 vec <hsa_op_reg_p> ssa_map)
+			 vec <hsa_op_reg_p> *ssa_map)
 {
   BrigType16_t mtype;
   mtype = mem_type_for_type (hsa_type_for_scalar_tree_type (TREE_TYPE (lhs),
@@ -1509,7 +1507,7 @@ gen_hsa_insns_for_store (tree lhs, hsa_op_base *src, hsa_bb *hbb,
 
 static void
 gen_hsa_insns_for_single_assignment (gimple assign, hsa_bb *hbb,
-				     vec <hsa_op_reg_p> ssa_map)
+				     vec <hsa_op_reg_p> *ssa_map)
 {
   tree lhs = gimple_assign_lhs (assign);
   tree rhs = gimple_assign_rhs1 (assign);
@@ -1616,7 +1614,7 @@ hsa_spill_out (hsa_insn_basic *insn, hsa_op_reg *spill_reg, hsa_op_reg **ptmp2)
 static void
 gen_hsa_cmp_insn_from_gimple (enum tree_code code, tree lhs, tree rhs,
 			      hsa_op_reg *dest, hsa_bb *hbb,
-			      vec <hsa_op_reg_p> ssa_map)
+			      vec <hsa_op_reg_p> *ssa_map)
 {
   BrigCompareOperation8_t compare;
 
@@ -1660,7 +1658,7 @@ gen_hsa_cmp_insn_from_gimple (enum tree_code code, tree lhs, tree rhs,
 
 static void
 gen_hsa_insns_for_operation_assignment (gimple assign, hsa_bb *hbb,
-					vec <hsa_op_reg_p> ssa_map)
+					vec <hsa_op_reg_p> *ssa_map)
 {
   int opcode;
 
@@ -1846,7 +1844,7 @@ gen_hsa_insns_for_operation_assignment (gimple assign, hsa_bb *hbb,
 
 static void
 gen_hsa_insns_for_cond_stmt (gimple cond, hsa_bb *hbb,
-			     vec <hsa_op_reg_p> ssa_map)
+			     vec <hsa_op_reg_p> *ssa_map)
 {
   hsa_op_reg *ctrl = new hsa_op_reg (BRIG_TYPE_B1);
   hsa_insn_br *cbr;
@@ -1867,10 +1865,15 @@ gen_hsa_insns_for_cond_stmt (gimple cond, hsa_bb *hbb,
 
 static void
 gen_hsa_insns_for_direct_call (gimple stmt, hsa_bb *hbb,
-			       vec <hsa_op_reg_p> ssa_map)
+			       vec <hsa_op_reg_p> *ssa_map)
 {
   hsa_insn_call *call_insn = new hsa_insn_call (gimple_call_fndecl (stmt));
-  hsa_insn_call_block *call_block_insn = new hsa_insn_call_block ();
+  hsa_cfun->called_functions.safe_push (call_insn->called_function);
+
+  /* Argument block start.  */
+  hsa_insn_arg_block *arg_start = new hsa_insn_arg_block
+    (BRIG_KIND_DIRECTIVE_ARG_BLOCK_START, call_insn);
+  hsa_append_insn (hbb, arg_start);
 
   /* Preparation of arguments that will be passed to function.  */
   const unsigned args = gimple_call_num_args (stmt);
@@ -1887,13 +1890,14 @@ gen_hsa_insns_for_direct_call (gimple stmt, hsa_bb *hbb,
       mem->operands[0] = src;
       mem->operands[1] = addr;
 
-      call_block_insn->input_args.safe_push (addr->symbol);
-      call_block_insn->input_arg_insns.safe_push (mem);
+      call_insn->input_args.safe_push (addr->symbol);
+      hsa_append_insn (hbb, mem);
 
       call_insn->args_symbols.safe_push (addr->symbol);
     }
 
   call_insn->args_code_list = new hsa_op_code_list (args);
+  hsa_append_insn (hbb, call_insn);
 
   tree result_type = TREE_TYPE (TREE_TYPE (gimple_call_fndecl (stmt)));
 
@@ -1916,22 +1920,20 @@ gen_hsa_insns_for_direct_call (gimple stmt, hsa_bb *hbb,
 	  result_insn->operands[1] = addr;
 	  set_reg_def (dst, result_insn);
 
-	  call_block_insn->output_arg_insn = result_insn;
+	  hsa_append_insn (hbb, result_insn);
 	}
 
-      call_block_insn->output_arg = addr->symbol;
+      call_insn->output_arg = addr->symbol;
       call_insn->result_symbol = addr->symbol;
       call_insn->result_code_list = new hsa_op_code_list (1);
     }
   else
     call_insn->result_code_list = new hsa_op_code_list (0);
 
-  call_block_insn->call_insn = call_insn;
-
-  if (result_insn)
-    call_block_insn->output_arg_insn = result_insn;
-
-  hsa_append_insn (hbb, call_block_insn);
+  /* Argument block start.  */
+  hsa_insn_arg_block *arg_end = new hsa_insn_arg_block
+    (BRIG_KIND_DIRECTIVE_ARG_BLOCK_END, call_insn);
+  hsa_append_insn (hbb, arg_end);
 }
 
 /* Generate HSA instructions for a return value instruction.
@@ -1941,7 +1943,7 @@ gen_hsa_insns_for_direct_call (gimple stmt, hsa_bb *hbb,
 
 static void
 gen_hsa_insns_for_return (greturn *stmt, hsa_bb *hbb,
-			vec <hsa_op_reg_p> ssa_map)
+			vec <hsa_op_reg_p> *ssa_map)
 {
   tree retval = gimple_return_retval (stmt);
   if (retval)
@@ -1969,11 +1971,10 @@ gen_hsa_insns_for_return (greturn *stmt, hsa_bb *hbb,
 
 static bool
 gen_hsa_insns_for_known_library_call (gimple stmt, hsa_bb *hbb,
-				      vec <hsa_op_reg_p> ssa_map)
+				      vec <hsa_op_reg_p> *ssa_map)
 {
   tree decl = gimple_call_fndecl (stmt);
-  gcc_checking_assert (DECL_NAME (decl));
-  const char *name = IDENTIFIER_POINTER (DECL_NAME (decl));
+  const char *name = get_declaration_name (decl);
 
   if (!strcmp (name, "omp_is_initial_device")
       || strcmp (name, "omp_is_initial_device"))
@@ -1997,7 +1998,7 @@ gen_hsa_insns_for_known_library_call (gimple stmt, hsa_bb *hbb,
 
 static void
 gen_hsa_insns_for_call (gimple stmt, hsa_bb *hbb,
-			vec <hsa_op_reg_p> ssa_map)
+			vec <hsa_op_reg_p> *ssa_map)
 {
   tree lhs = gimple_call_lhs (stmt);
   hsa_op_reg *dest;
@@ -2143,7 +2144,7 @@ specialop:
 
 static void
 gen_hsa_insns_for_gimple_stmt (gimple stmt, hsa_bb *hbb,
-			       vec <hsa_op_reg_p> ssa_map)
+			       vec <hsa_op_reg_p> *ssa_map)
 {
   switch (gimple_code (stmt))
     {
@@ -2185,7 +2186,7 @@ gen_hsa_insns_for_gimple_stmt (gimple stmt, hsa_bb *hbb,
 
 static void
 gen_hsa_phi_from_gimple_phi (gimple gphi, hsa_bb *hbb,
-			     vec <hsa_op_reg_p> ssa_map)
+			     vec <hsa_op_reg_p> *ssa_map)
 {
   hsa_insn_phi *hphi;
   unsigned count = gimple_phi_num_args (gphi);
@@ -2287,7 +2288,7 @@ hsa_init_new_bb (basic_block bb)
    maps gimple SSA names to HSA pseudo registers.  */
 
 static void
-gen_body_from_gimple (vec <hsa_op_reg_p> ssa_map)
+gen_body_from_gimple (vec <hsa_op_reg_p> *ssa_map)
 {
   basic_block bb;
 
@@ -2321,12 +2322,64 @@ 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)
+{
+  tree parm;
+  unsigned i;
+
+  f->input_args_count = get_function_arg_count (decl);
+  f->input_args = XCNEWVEC (hsa_symbol, f->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->input_args_count)
+	break;
+
+      tree v = TREE_VALUE (parm);
+      f->input_args[i].type = hsa_type_for_tree_type (v, &f->input_args[i].dim);
+      f->input_args[i].segment = BRIG_SEGMENT_ARG;
+      f->input_args[i].linkage = BRIG_LINKAGE_NONE;
+      f->input_args[i].name_number = i;
+    }
+
+  tree result_type = TREE_TYPE (TREE_TYPE (decl));
+  if (!VOID_TYPE_P (result_type))
+    {
+      f->output_arg = XCNEW (hsa_symbol);
+      f->output_arg->type = hsa_type_for_tree_type (result_type,
+						   &f->output_arg->dim);
+      f->output_arg->segment = BRIG_SEGMENT_ARG;
+      f->output_arg->linkage = BRIG_LINKAGE_NONE;
+      f->output_arg->name = "res";
+    }
+}
+
 /* Generate the vector of parameters of the HSA representation of the current
    function.  This also includes the output parameter representing the
    result.  */
 
 static void
-gen_function_parameters (vec <hsa_op_reg_p> ssa_map)
+gen_function_def_parameters (hsa_function_representation *f,
+			     vec <hsa_op_reg_p> *ssa_map)
 {
   tree parm;
   int i, count = 0;
@@ -2334,30 +2387,33 @@ gen_function_parameters (vec <hsa_op_reg_p> ssa_map)
   for (parm = DECL_ARGUMENTS (cfun->decl); parm; parm = DECL_CHAIN (parm))
     count++;
 
-  hsa_cfun->input_args_count = count;
-  hsa_cfun->input_args = XCNEWVEC (hsa_symbol, count);
+  ENTRY_BLOCK_PTR_FOR_FN (cfun)->aux = &f->prologue;
+  f->prologue.bb = ENTRY_BLOCK_PTR_FOR_FN (cfun);
+
+  f->input_args_count = count;
+  f->input_args = XCNEWVEC (hsa_symbol, f->input_args_count);
   for (parm = DECL_ARGUMENTS (cfun->decl), i = 0;
        parm;
        parm = DECL_CHAIN (parm), i++)
     {
       struct hsa_symbol **slot;
 
-      fillup_sym_for_decl (parm, &hsa_cfun->input_args[i]);
-      hsa_cfun->input_args[i].segment = hsa_cfun->kern_p ? BRIG_SEGMENT_KERNARG :
+      fillup_sym_for_decl (parm, &f->input_args[i]);
+      f->input_args[i].segment = f->kern_p ? BRIG_SEGMENT_KERNARG :
 				       BRIG_SEGMENT_ARG;
 
-      hsa_cfun->input_args[i].linkage = BRIG_LINKAGE_FUNCTION;
+      f->input_args[i].linkage = BRIG_LINKAGE_FUNCTION;
       if (!DECL_NAME (parm))
 	{
 	  /* FIXME: Just generate some UID.  */
 	  sorry ("Support for HSA does not implement anonymous C++ parameters");
 	  return;
 	}
-      hsa_cfun->input_args[i].name = IDENTIFIER_POINTER (DECL_NAME (parm));
-      slot = hsa_cfun->local_symbols->find_slot (&hsa_cfun->input_args[i],
+      f->input_args[i].name = IDENTIFIER_POINTER (DECL_NAME (parm));
+      slot = f->local_symbols->find_slot (&f->input_args[i],
 						INSERT);
       gcc_assert (!*slot);
-      *slot = &hsa_cfun->input_args[i];
+      *slot = &f->input_args[i];
 
       if (is_gimple_reg (parm))
 	{
@@ -2375,7 +2431,7 @@ gen_function_parameters (vec <hsa_op_reg_p> ssa_map)
 	      mem->operands[1] = addr;
 	      set_reg_def (dest, mem);
 	      gcc_assert (!addr->reg);
-	      hsa_append_insn (&hsa_cfun->prologue, mem);
+	      hsa_append_insn (&f->prologue, mem);
 	    }
 	}
     }
@@ -2384,17 +2440,34 @@ gen_function_parameters (vec <hsa_op_reg_p> ssa_map)
     {
       struct hsa_symbol **slot;
 
-      hsa_cfun->output_arg = XCNEW (hsa_symbol);
-      fillup_sym_for_decl (DECL_RESULT (cfun->decl), hsa_cfun->output_arg);
-      hsa_cfun->output_arg->segment = BRIG_SEGMENT_ARG;
-      hsa_cfun->output_arg->linkage = BRIG_LINKAGE_FUNCTION;
-      hsa_cfun->output_arg->name = "res";
-      slot = hsa_cfun->local_symbols->find_slot (hsa_cfun->output_arg, INSERT);
+      f->output_arg = XCNEW (hsa_symbol);
+      fillup_sym_for_decl (DECL_RESULT (cfun->decl), f->output_arg);
+      f->output_arg->segment = BRIG_SEGMENT_ARG;
+      f->output_arg->linkage = BRIG_LINKAGE_FUNCTION;
+      f->output_arg->name = "res";
+      slot = f->local_symbols->find_slot (f->output_arg, INSERT);
       gcc_assert (!*slot);
-      *slot = hsa_cfun->output_arg;
+      *slot = f->output_arg;
     }
 }
 
+/* Generate function representation that corresponds to
+   a function declaration.  */
+
+hsa_function_representation *
+hsa_generate_function_declaration (tree decl)
+{
+  hsa_function_representation *fun = XCNEW (hsa_function_representation);
+
+  fun->declaration_p = true;
+  fun->decl = decl;
+  fun->name = xstrdup (get_declaration_name (decl));
+
+  gen_function_decl_parameters (fun, decl);
+
+  return fun;
+}
+
 /* Generate HSAIL representation of the current function and write into a
    special section of the output file.  If KERNEL is set, the function will be
    considered an HSA kernel callable from the host, otherwise it will be
@@ -2406,20 +2479,21 @@ generate_hsa (bool kernel)
   vec <hsa_op_reg_p> ssa_map = vNULL;
 
   hsa_init_data_for_cfun ();
+  hsa_cfun->decl = cfun->decl;
   hsa_cfun->kern_p = kernel;
 
   ssa_map.safe_grow_cleared (SSANAMES (cfun)->length ());
   hsa_cfun->name
-    = xstrdup (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)));
+    = 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_parameters (ssa_map);
+  gen_function_def_parameters (hsa_cfun, &ssa_map);
   if (seen_error ())
     goto fail;
-  gen_body_from_gimple (ssa_map);
+  gen_body_from_gimple (&ssa_map);
   if (seen_error ())
     goto fail;
 
diff --git a/gcc/hsa-regalloc.c b/gcc/hsa-regalloc.c
index 5e34f9c..2521b16 100644
--- a/gcc/hsa-regalloc.c
+++ b/gcc/hsa-regalloc.c
@@ -58,6 +58,7 @@ naive_process_phi (hsa_insn_phi *phi)
   unsigned count = phi->operands.length ();
   for (unsigned i = 0; i < count; i++)
     {
+      gcc_checking_assert (phi->operands[i]);
       hsa_op_base *op = phi->operands[i];
       hsa_bb *hbb;
       edge e;
@@ -247,7 +248,6 @@ hsa_num_def_ops (hsa_insn_basic *insn)
 	return 1;
 
       case BRIG_OPCODE_NOP:
-      case HSA_OPCODE_CALL_BLOCK:
 	return 0;
 
       case BRIG_OPCODE_EXPAND:
@@ -311,7 +311,7 @@ hsa_num_def_ops (hsa_insn_basic *insn)
       case BRIG_OPCODE_CALL:
       case BRIG_OPCODE_SCALL:
       case BRIG_OPCODE_ICALL:
-	return 1; /* ??? */
+	return 0;
 
       case BRIG_OPCODE_RET:
 	return 0;
@@ -341,6 +341,9 @@ hsa_num_def_ops (hsa_insn_basic *insn)
       case BRIG_OPCODE_GROUPBASEPTR:
       case BRIG_OPCODE_KERNARGBASEPTR:
 	return 1; /* ??? */
+
+      case HSA_OPCODE_ARG_BLOCK:
+	return 0;
     }
 }
 
@@ -508,72 +511,6 @@ spill_at_interval (hsa_op_reg *reg, vec<hsa_op_reg*> *active)
   cand->spill_sym->name_number = cand->order;
 }
 
-/* Visit instruction INSN and fill in vector IND2REG if the instruction
-   contains a register (in memory).  Number all insns by a global counter,
-   passed by INSN_ORDER argument.  */
-
-static void
-visit_insn (hsa_insn_basic *insn, vec<hsa_op_reg*> &ind2reg, int &insn_order)
-{
-  unsigned opi;
-  unsigned count = insn->operands.length ();
-  insn->number = insn_order++;
-  for (opi = 0; opi < count; opi++)
-    {
-      gcc_checking_assert (insn->operands[opi]);
-      hsa_op_reg **regaddr = insn_reg_addr (insn, opi);
-      if (regaddr)
-	ind2reg[(*regaddr)->order] = *regaddr;
-    }
-}
-
-/* Remove definition in INSN according to bitmap WORK list.  */
-
-static void
-remove_def_in_insn (bitmap &work, hsa_insn_basic *insn)
-{
-  unsigned opi;
-  unsigned ndefs = hsa_num_def_ops (insn);
-  for (opi = 0; opi < ndefs && insn->operands[opi]; opi++)
-    {
-      gcc_checking_assert (insn->operands[opi]);
-      hsa_op_reg **regaddr = insn_reg_addr (insn, opi);
-      if (regaddr)
-	bitmap_clear_bit (work, (*regaddr)->order);
-    }
-  unsigned count = insn->operands.length ();
-  for (; opi < count; opi++)
-    {
-      gcc_checking_assert (insn->operands[opi]);
-      hsa_op_reg **regaddr = insn_reg_addr (insn, opi);
-      if (regaddr)
-	bitmap_set_bit (work, (*regaddr)->order);
-    }
-}
-
-/* Merge live range for an instruction INSN.  */
-
-static void
-merge_live_range_for_insn (hsa_insn_basic *insn)
-{
-  unsigned opi;
-  unsigned ndefs = hsa_num_def_ops (insn);
-  unsigned count = insn->operands.length ();
-  for (opi = 0; opi < count; opi++)
-    {
-      gcc_checking_assert (insn->operands[opi]);
-      hsa_op_reg **regaddr = insn_reg_addr (insn, opi);
-      if (regaddr)
-	{
-	  hsa_op_reg *reg = *regaddr;
-	  if (opi < ndefs)
-	    note_lr_begin (reg, insn->number);
-	  else
-	    note_lr_end (reg, insn->number);
-	}
-    }
-}
-
 /* Given the global register state CLASSES allocate all HSA virtual
    registers either to hardregs or to a spill symbol.  */
 
@@ -606,16 +543,14 @@ linear_scan_regalloc (struct reg_class_desc *classes)
       hsa_insn_basic *insn;
       for (insn = hbb->first_insn; insn; insn = insn->next)
 	{
-	  visit_insn (insn, ind2reg, insn_order);
-
-	  if (is_a <hsa_insn_call_block *> (insn))
+	  unsigned opi;
+	  insn->number = insn_order++;
+	  for (opi = 0; opi < insn->operands.length (); opi++)
 	    {
-	      /* HSA call block insn contains insns that are used for passing
-		 arguments and getting a return value, if returned.  */
-	      hsa_insn_call_block *call = dyn_cast <hsa_insn_call_block *>
-		(insn);
-	      for (unsigned j = 0; j < call->input_arg_insns.length (); j++)
-		visit_insn (call->input_arg_insns[j], ind2reg, insn_order);
+	      gcc_checking_assert (insn->operands[opi]);
+	      hsa_op_reg **regaddr = insn_reg_addr (insn, opi);
+	      if (regaddr)
+		ind2reg[(*regaddr)->order] = *regaddr;
 	    }
 	}
     }
@@ -661,17 +596,21 @@ linear_scan_regalloc (struct reg_class_desc *classes)
 	  hsa_insn_basic *insn;
 	  for (insn = hbb->last_insn; insn; insn = insn->prev)
 	    {
-	      remove_def_in_insn (work, insn);
-	      if (is_a <hsa_insn_call_block *> (insn))
+	      unsigned opi;
+	      unsigned ndefs = hsa_num_def_ops (insn);
+	      for (opi = 0; opi < ndefs && insn->operands[opi]; opi++)
+		{
+		  gcc_checking_assert (insn->operands[opi]);
+		  hsa_op_reg **regaddr = insn_reg_addr (insn, opi);
+		  if (regaddr)
+		    bitmap_clear_bit (work, (*regaddr)->order);
+		}
+	      for (; opi < insn->operands.length (); opi++)
 		{
-		  /* HSA call block insn contains insns that are used for
-		     passing arguments and getting a return value,
-		     if returned.  */
-		  hsa_insn_call_block *call = dyn_cast <hsa_insn_call_block *>
-		    (insn);
-
-		  for (int j = call->input_arg_insns.length () - 1; j >= 0; j--)
-		    remove_def_in_insn (work, call->input_arg_insns[j]);
+		  gcc_checking_assert (insn->operands[opi]);
+		  hsa_op_reg **regaddr = insn_reg_addr (insn, opi);
+		  if (regaddr)
+		    bitmap_set_bit (work, (*regaddr)->order);
 		}
 	    }
 
@@ -705,17 +644,20 @@ linear_scan_regalloc (struct reg_class_desc *classes)
 
       for (insn = hbb->last_insn; insn; insn = insn->prev)
 	{
-	  merge_live_range_for_insn (insn);
-
-	  if (is_a <hsa_insn_call_block *> (insn))
+	  unsigned opi;
+	  unsigned ndefs = hsa_num_def_ops (insn);
+	  for (opi = 0; opi < insn->operands.length (); opi++)
 	    {
-	      /* HSA call block insn contains insns that are used for passing
-		 arguments and getting a return value, if returned.  */
-	      hsa_insn_call_block *call = dyn_cast <hsa_insn_call_block *>
-		(insn);
-
-	      for (int j = call->input_arg_insns.length () - 1; j >= 0; j--)
-		merge_live_range_for_insn (call->input_arg_insns[j]);
+	      gcc_checking_assert (insn->operands[opi]);
+	      hsa_op_reg **regaddr = insn_reg_addr (insn, opi);
+	      if (regaddr)
+		{
+		  hsa_op_reg *reg = *regaddr;
+		  if (opi < ndefs)
+		    note_lr_begin (reg, insn->number);
+		  else
+		    note_lr_end (reg, insn->number);
+		}
 	    }
 	}
       if (hbb->first_insn)
diff --git a/gcc/hsa.c b/gcc/hsa.c
index fbf7370..730236b 100644
--- a/gcc/hsa.c
+++ b/gcc/hsa.c
@@ -303,9 +303,9 @@ hsa_destroy_insn (hsa_insn_basic *insn)
       call->~hsa_insn_call ();
       return;
     }
-  if (hsa_insn_call_block *block = dyn_cast <hsa_insn_call_block *> (insn))
+  if (hsa_insn_arg_block *block = dyn_cast <hsa_insn_arg_block *> (insn))
     {
-      block->~hsa_insn_call_block ();
+      block->~hsa_insn_arg_block ();
       return;
     }
   insn->~hsa_insn_basic ();
@@ -352,6 +352,9 @@ hsa_get_decl_kernel_mapping_name (unsigned i)
 void
 hsa_free_decl_kernel_mapping (void)
 {
+  if (hsa_decl_kernel_mapping == NULL)
+    return;
+
   for (unsigned i = 0; i < hsa_decl_kernel_mapping->length (); ++i)
     free ((*hsa_decl_kernel_mapping)[i].name);
   ggc_free (hsa_decl_kernel_mapping);
@@ -367,4 +370,17 @@ hsa_sanitize_name (char *p)
       *p = '_';
 }
 
+/* Return declaration name if exists.  */
+
+const char *
+get_declaration_name (tree decl)
+{
+  if (!DECL_NAME (decl))
+    sorry ("Support for HSA does not implement anonymous declarations");
+  else
+    return IDENTIFIER_POINTER (DECL_NAME (decl));
+
+  return NULL;
+}
+
 #include "gt-hsa.h"
diff --git a/gcc/hsa.h b/gcc/hsa.h
index 1cff6db..b43a991 100644
--- a/gcc/hsa.h
+++ b/gcc/hsa.h
@@ -277,7 +277,7 @@ is_a_helper <hsa_op_code_list *>::test (hsa_op_base *p)
    represent it nevertheless.  */
 
 #define HSA_OPCODE_PHI (-1)
-#define HSA_OPCODE_CALL_BLOCK (-2)
+#define HSA_OPCODE_ARG_BLOCK (-2)
 
 /* The number of operand pointers we can directly in an instruction.  */
 #define HSA_BRIG_INT_STORAGE_OPERANDS 5
@@ -530,6 +530,15 @@ public:
   /* Called function */
   tree called_function;
 
+  /* Input formal arguments.  */
+  auto_vec <hsa_symbol *> input_args;
+
+  /* Input arguments store instructions.  */
+  auto_vec <hsa_insn_mem *> input_arg_insns;
+
+  /* Output argument, can be NULL for void functions.  */
+  hsa_symbol *output_arg;
+
   /* Called function code reference.  */
   hsa_op_code_ref func;
 
@@ -568,23 +577,14 @@ is_a_helper <hsa_insn_call *>::test (hsa_insn_basic *p)
    Emission of the instruction will produce multiple
    HSAIL instructions.  */
 
-class hsa_insn_call_block : public hsa_insn_basic
+class hsa_insn_arg_block : public hsa_insn_basic
 {
 public:
-  hsa_insn_call_block ();
+  hsa_insn_arg_block (BrigKind brig_kind, hsa_insn_call * call);
   void *operator new (size_t);
 
-  /* Input formal arguments.  */
-  auto_vec <hsa_symbol *> input_args;
-
-  /* Input arguments store instructions.  */
-  auto_vec <hsa_insn_mem *> input_arg_insns;
-
-  /* Output argument, can be NULL for void functions.  */
-  hsa_symbol *output_arg;
-
-  /* Output argument load instruction.  */
-  hsa_insn_mem *output_arg_insn;
+  /* Kind of argument block.  */
+  BrigKind kind;
 
   /* Call instruction.  */
   hsa_insn_call *call_insn;
@@ -599,9 +599,9 @@ private:
 template <>
 template <>
 inline bool
-is_a_helper <hsa_insn_call_block *>::test (hsa_insn_basic *p)
+is_a_helper <hsa_insn_arg_block *>::test (hsa_insn_basic *p)
 {
-  return (p->opcode == HSA_OPCODE_CALL_BLOCK);
+  return (p->opcode == HSA_OPCODE_ARG_BLOCK);
 }
 
 /* Basic block of HSA instructions.  */
@@ -713,7 +713,7 @@ public:
   /* 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.  */
-  int input_args_count;
+  unsigned input_args_count;
 
   /* Number of allocated register structures.  */
   int reg_count;
@@ -726,6 +726,9 @@ public:
   /* Vector of pointers to spill symbols.  */
   vec <struct hsa_symbol *> spill_symbols;
 
+  /* Vector of called function declarations.  */
+  vec <tree> called_functions;
+
   /* Instructions to be executed before the first BB from gimple.  It's label
    is zero and must not be referenced, of course there are no PHIs.  */
   hsa_bb prologue;
@@ -738,6 +741,12 @@ public:
 
   /* True if the function is kernel function.  */
   bool kern_p;
+
+  /* True if the function representation is a declaration.  */
+  bool declaration_p;
+
+  /* Function declaration tree.  */
+  tree decl;
 };
 
 /* in hsa.c */
@@ -758,6 +767,7 @@ tree hsa_get_decl_kernel_mapping_decl (unsigned i);
 char *hsa_get_decl_kernel_mapping_name (unsigned i);
 void hsa_free_decl_kernel_mapping (void);
 void hsa_sanitize_name (char *p);
+const char *get_declaration_name (tree decl);
 
 /* In hsa-gen.c.  */
 void hsa_build_append_simple_mov (hsa_op_reg *, hsa_op_base *, hsa_bb *);
@@ -765,6 +775,7 @@ hsa_symbol *hsa_get_spill_symbol (BrigType16_t);
 hsa_op_reg *hsa_spill_in (hsa_insn_basic *, hsa_op_reg *, hsa_op_reg **);
 hsa_op_reg *hsa_spill_out (hsa_insn_basic *, hsa_op_reg *, hsa_op_reg **);
 hsa_bb *hsa_init_new_bb (basic_block);
+hsa_function_representation *hsa_generate_function_declaration (tree decl);
 
 /* In hsa-regalloc.c.  */
 void hsa_regalloc (void);
-- 
2.1.4


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