diff mbox

[hsa] C++ification of operands and instructions

Message ID 20150626140135.GM18873@virgil.suse
State New
Headers show

Commit Message

Martin Jambor June 26, 2015, 2:01 p.m. UTC
Hello,

the following patch provides constructors and operators new for
(almost) all classes representing operands, instructions and
basic-blocks in HSA.  

There were three reasons for this.  First and foremost, some classes
already contained auto_vec fields which meant they had constructors,
which however were not properly invoked.  Even if they were, many of
them were memset to zero after allocation, which surprisingly worked
but certainly was not correct and was susceptible to weird breakage in
future.  Second, we needed to allow more operands than the statically
allocated five for phi-nodes and I wanted to use an auto_vec for that
as well.  Finally, it just makes sense to use the standard C++
concepts as much as possible in completely new code and, to my best
knowledge this is it.

The patch relies on the fact that the pool allocator does not invoke
placement new, which would construct the object twice if it did not
fail because I made many default constructors private.  Martin already
has another allocator-pool patch in the works that will provide
untyped allocators for these types of usage.  I will merge from trunk
again after these get in.

Finally, the auto_vecs in code reference operands mean that hsa_cfun
gets constructors and destructors, which is undesirable for statically
allocated object, so I made it a pointer to a dynamically allocated
ones.

I have committed the patch after standard testing so that Martin can
re-base his work now.  I will post a followup which will change how we
do some necessary destruction of the HSAIL representation soon.

Thanks,

Martin


2015-06-26  Martin Jambor  <mjambor@suse.cz>

	* hsa.h (hsa_bb): Made a class with constructors, destructor and a
	new operator.
	(hsa_function_representation): Turned into a class, added
	constructor and destructor.
	(hsa_cfun): Turned into a pointer update all users.

	* hsa-gen.c (hsa_bb::hsa_bb): New.
	(hsa_bb::operator new): Likewise.
	(hsa_bb::~hsa_bb): Likewise.
	(hsa_deinit_data_for_cfun): Call destructor.

2015-06-26  Martin Jambor  <mjambor@suse.cz>

	* hsa.h (hsa_insn_basic): Use class keyword, added constructors and
	new operator, operands turned into a vector.
	(hsa_insn_phi): Use class keyword, added a constructor and new
	operator.
	(hsa_insn_br): Likewise.
	(hsa_insn_cmp): Likewise.
	(hsa_insn_mem): Likewise.
	(hsa_insn_atomic): Likewise.
	(hsa_insn_seg): Likewise.
	(hsa_insn_addr): Removed, converted all users to use hsa_insn_basic.
	(hsa_insn_call): Use class keyword, added a constructor and new
	operator.
	(hsa_insn_call_block): Likewise.
	* hsa-gen.c (hsa_insn_basic::hsa_insn_basic): New.
	(hsa_insn_basic::operator new) Likewise.
	(hsa_alloc_basic_insn): Removed, turned all users into uses of
	operator new.
	(hsa_insn_phi::hsa_insn_phi): New.
	(hsa_insn_phi::operator new): Likewise.
	(gen_hsa_phi_from_gimple_phi): Use operator new.  Removed max
	predecessor number limitation.
	(hsa_insn_br::hsa_insn_br): New.
	(hsa_insn_br::operator new): Likewise.
	(hsa_build_cbr_insn): Removed, turned all users into uses of
	operator new.
	(hsa_insn_cmp::hsa_insn_cmp): New.
	(hsa_insn_cmp::operator new): Likewise.
	(hsa_alloc_cmp_insn): Removed, turned all users into uses of
	operator new.
	(hsa_insn_mem::hsa_insn_mem): New.
	(hsa_insn_mem::operator new): Likewise.
	(hsa_alloc_mem_insn): Removed, turned all users into uses of
	operator new.
	(hsa_insn_atomic::hsa_insn_atomic) New.
	(hsa_insn_atomic::operator new): Likewise.
	(hsa_alloc_atomic_insn): Removed, turned all users into uses of
	operator new.
	(hsa_allocp_inst_addr): Removed.
	(hsa_alloc_addr_insn): Likewise.
	(hsa_insn_seg::hsa_insn_seg): New.
	(hsa_insn_seg::operator new): Likewise.
	(hsa_alloc_seg_insn): Removed, turned all users into uses of operator
	new.
	(hsa_insn_call::hsa_insn_call): New.
	(hsa_insn_call::operator new): Likewise.
	(hsa_alloc_call_insn): Removed, turned all users into uses of operator
	new.
	(hsa_insn_call_block::hsa_insn_call_block): New.
	(hsa_insn_call_block::operator new): Likewise.
	(hsa_alloc_call_block_insn): Removed, turned all users into uses of
	operator new.
	* hsa-brig.c (emit_insn): Check LDA instruction according to opcode,
	not class type.
	(emit_cvt_insn): Use auto_vec also for operand offsets.
	(emit_basic_insn): Likewise.
	* hsa-dump.c (dump_hsa_insn): Check for LDA instructions based on
	opcode, not class.
	(dump_hsa_insn): Adjusted to use operand vector.
	(dump_hsa_insn): Likewise.
	* hsa-regalloc.c (naive_process_phi): Likewise.
	(linear_scan_regalloc): Likewise.
	(hsa_num_def_ops): Handle HSA_OPCODE_CALL_BLOCK.

2015-06-26  Martin Jambor  <mjambor@suse.cz>

	* hsa.h (hsa_op_base): Use class keyword, add constructors.
	(hsa_op_with_type): Likewise.
	(hsa_op_immed): Use class keyword, add constructors and a new
	operator.
	(hsa_op_reg): Likewise.
	(hsa_op_address): Likewise.
	(hsa_op_code_ref): Use class keyword, add constructors.
	(hsa_op_code_list): Use class keyword, add constructors and a new
	operator.

	* hsa-gen.c (hsa_op_with_type::hsa_op_with_type): New.
	(hsa_op_immed): Likewise.
	(hsa_op_immed::operator new): Likewise.
	(hsa_alloc_immed_op): Removed, replaced all uses by allocation with
	new.
	(hsa_op_reg::hsa_op_reg): New.
	(hsa_op_reg::operator new): Likewise.
	(hsa_alloc_reg_op): Removed, replaced all uses by allocation with new.
	(hsa_op_address::hsa_op_reg): New.
	(hsa_op_address::operator new): Likewise.
	(hsa_alloc_addr_op): Removed, replaced all uses by allocation with new.
	(hsa_op_code_ref::hsa_op_code_ref): New.
	(hsa_op_code_list::hsa_op_code_list): Likewise.
	(hsa_op_code_list::operator new): Likewise.
	(hsa_alloc_code_list_op): Removed, replaced all uses by allocation
	with new.
diff mbox

Patch

diff --git a/gcc/hsa-brig.c b/gcc/hsa-brig.c
index 8caa964..d06fe42 100644
--- a/gcc/hsa-brig.c
+++ b/gcc/hsa-brig.c
@@ -534,28 +534,28 @@  emit_function_directives (void)
   BrigDirectiveExecutable *ptr_to_fndir;
   hsa_symbol *sym;
 
-  name_offset = brig_emit_string (hsa_cfun.name, '&');
+  name_offset = brig_emit_string (hsa_cfun->name, '&');
   inarg_off = brig_code.total_size + sizeof(fndir)
-    + (hsa_cfun.output_arg ? sizeof (struct BrigDirectiveVariable) : 0);
+    + (hsa_cfun->output_arg ? sizeof (struct BrigDirectiveVariable) : 0);
   scoped_off = inarg_off
-    + hsa_cfun.input_args_count * sizeof (struct BrigDirectiveVariable);
+    + 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 ();
+	 = 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 ();
+  count += hsa_cfun->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 (hsa_cfun->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 (hsa_cfun->input_args_count);
+  fndir.outArgCount = htole16 (hsa_cfun->output_arg ? 1 : 0);
   fndir.firstInArg = htole32 (inarg_off);
   fndir.firstCodeBlockEntry = htole32 (scoped_off);
   fndir.nextModuleEntry = htole32 (next_toplev_off);
@@ -579,20 +579,20 @@  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]);
+  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 ();
+	 = 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++)
+  for (int i = 0; hsa_cfun->spill_symbols.iterate (i, &sym); i++)
     {
       emit_directive_variable (sym);
       brig_insn_count++;
@@ -1100,7 +1100,7 @@  emit_atomic_insn (hsa_insn_atomic *mem)
    necessary operands for writing .  */
 
 static void
-emit_addr_insn (hsa_insn_addr *insn)
+emit_addr_insn (hsa_insn_basic *insn)
 {
   struct BrigInstAddr repr;
   BrigOperandOffset32_t operand_offsets[2];
@@ -1220,8 +1220,7 @@  emit_branch_insn (hsa_insn_br *br)
   edge e;
 
   /* At the moment we only handle direct conditional jumps.  */
-  gcc_assert (br->opcode == BRIG_OPCODE_CBR
-	      && !br->operands[2]);
+  gcc_assert (br->opcode == BRIG_OPCODE_CBR);
   repr.base.base.byteCount = htole16 (sizeof (repr));
   repr.base.base.kind = htole16 (BRIG_KIND_INST_BR);
   repr.base.opcode = htole16 (br->opcode);
@@ -1261,26 +1260,24 @@  emit_cvt_insn (hsa_insn_basic *insn)
 {
   struct BrigInstCvt repr;
   BrigType16_t srctype;
-  BrigOperandOffset32_t operand_offsets[HSA_OPERANDS_PER_INSN];
-  uint32_t byteCount, operand_count=0;
+  auto_vec<BrigOperandOffset32_t, HSA_BRIG_INT_STORAGE_OPERANDS> operand_offsets;
+  uint32_t byteCount, operand_count = insn->operands.length ();
 
   repr.base.base.byteCount = htole16 (sizeof (repr));
   repr.base.base.kind = htole16 (BRIG_KIND_INST_CVT);
   repr.base.opcode = htole16 (insn->opcode);
   repr.base.type = htole16 (insn->type);
 
-  for (int i = 0; i < HSA_OPERANDS_PER_INSN; i++)
-    if (insn->operands[i])
-      {
-        operand_offsets[i] = htole32 (enqueue_op (insn->operands[i]));
-        operand_count = operand_count + 1;
-      }
-    else
-      operand_offsets[i] = 0;
+  operand_offsets.safe_grow_cleared (operand_count);
+  for (unsigned i = 0; i < operand_count; i++)
+    {
+      gcc_checking_assert (insn->operands[i]);
+      operand_offsets[i] = htole32 (enqueue_op (insn->operands[i]));
+    }
 
   byteCount = htole32 (4 * operand_count) ;
   repr.base.operands = htole32 (brig_data.add (&byteCount, sizeof (byteCount)));
-  brig_data.add (&operand_offsets,
+  brig_data.add (operand_offsets.address (),
 		 operand_count * sizeof (BrigOperandOffset32_t));
 
   if (is_a <hsa_op_reg *> (insn->operands[1]))
@@ -1414,8 +1411,8 @@  emit_basic_insn (hsa_insn_basic *insn)
   /* We assume that BrigInstMod has a BrigInstBasic prefix.  */
   struct BrigInstMod repr;
   BrigType16_t type;
-  BrigOperandOffset32_t operand_offsets[HSA_OPERANDS_PER_INSN];
-  uint32_t byteCount, operand_count = 0;
+  auto_vec<BrigOperandOffset32_t, HSA_BRIG_INT_STORAGE_OPERANDS> operand_offsets;
+  uint32_t byteCount, operand_count = insn->operands.length ();
 
   if (insn->opcode == BRIG_OPCODE_CVT)
     {
@@ -1443,18 +1440,16 @@  emit_basic_insn (hsa_insn_basic *insn)
     }
   repr.base.type = htole16 (type);
 
-  for (int i = 0; i < HSA_OPERANDS_PER_INSN; i++)
-    if (insn->operands[i])
-      {
-	operand_offsets[i] = htole32 (enqueue_op (insn->operands[i]));
-	operand_count = operand_count + 1;
-      }
-    else
-      operand_offsets[i] = 0;
+  operand_offsets.safe_grow_cleared (operand_count);
+  for (unsigned i = 0; i < operand_count; i++)
+    {
+      gcc_checking_assert (insn->operands[i]);
+      operand_offsets[i] = htole32 (enqueue_op (insn->operands[i]));
+    }
 
   byteCount = htole32 (4 * operand_count) ;
   repr.base.operands = htole32 (brig_data.add (&byteCount, sizeof (byteCount)));
-  brig_data.add (&operand_offsets,
+  brig_data.add (operand_offsets.address (),
 		 operand_count * sizeof (BrigOperandOffset32_t));
   brig_data.round_size_up (4);
 
@@ -1497,9 +1492,9 @@  emit_insn (hsa_insn_basic *insn)
       emit_memory_insn (mem);
       return;
     }
-  if (hsa_insn_addr *addr = dyn_cast <hsa_insn_addr *> (insn))
+  if (insn->opcode == BRIG_OPCODE_LDA)
     {
-      emit_addr_insn (addr);
+      emit_addr_insn (insn);
       return;
     }
   if (hsa_insn_seg *seg = dyn_cast <hsa_insn_seg *> (insn))
diff --git a/gcc/hsa-dump.c b/gcc/hsa-dump.c
index 3492fd1..2519765 100644
--- a/gcc/hsa-dump.c
+++ b/gcc/hsa-dump.c
@@ -720,7 +720,8 @@  dump_hsa_insn (FILE *f, hsa_insn_basic *insn, int indent)
       bool first = true;
       dump_hsa_reg (f, phi->dest, true);
       fprintf (f, " = PHI <");
-      for (int i = 0; i < HSA_OPERANDS_PER_INSN; i++)
+      unsigned count = phi->operands.length ();
+      for (unsigned i = 0; i < count; i++)
 	{
 	  if (!phi->operands[i])
 	    break;
@@ -780,17 +781,16 @@  dump_hsa_insn (FILE *f, hsa_insn_basic *insn, int indent)
       dump_hsa_address (f, addr);
       fprintf (f, "\n");
     }
-  else if (is_a <hsa_insn_addr *> (insn))
+  else if (insn->opcode == BRIG_OPCODE_LDA)
     {
-      hsa_insn_addr *ia = as_a <hsa_insn_addr *> (insn);
-      hsa_op_address *addr = as_a <hsa_op_address *> (ia->operands[1]);
+      hsa_op_address *addr = as_a <hsa_op_address *> (insn->operands[1]);
 
-      fprintf (f, "%s", hsa_opcode_name (ia->opcode));
+      fprintf (f, "%s", hsa_opcode_name (insn->opcode));
       if (addr->symbol)
 	fprintf (f, "_%s", hsa_seg_name (addr->symbol->segment));
-      fprintf (f, "_%s ", hsa_type_name (ia->type));
+      fprintf (f, "_%s ", hsa_type_name (insn->type));
 
-      dump_hsa_imm_or_reg (f, ia->operands[0]);
+      dump_hsa_imm_or_reg (f, insn->operands[0]);
       fprintf (f, ", ");
       dump_hsa_address (f, addr);
       fprintf (f, "\n");
@@ -891,7 +891,8 @@  dump_hsa_insn (FILE *f, hsa_insn_basic *insn, int indent)
       fprintf (f, "%s_%s ", hsa_opcode_name (insn->opcode),
 	       hsa_type_name (insn->type));
 
-      for (int i = 0; i < HSA_OPERANDS_PER_INSN; i++)
+      unsigned count = insn->operands.length ();
+      for (unsigned i = 0; i < count; i++)
 	{
 	  hsa_op_base *op = insn->operands[i];
 
@@ -972,9 +973,9 @@  dump_hsa_cfun (FILE *f)
 {
   basic_block bb;
 
-  fprintf (f, "\nHSAIL IL for %s\n", hsa_cfun.name);
+  fprintf (f, "\nHSAIL IL for %s\n", hsa_cfun->name);
 
-  dump_hsa_bb (f, &hsa_cfun.prologue);
+  dump_hsa_bb (f, &hsa_cfun->prologue);
   FOR_EACH_BB_FN (bb, cfun)
   {
     hsa_bb *hbb = (struct hsa_bb *) bb->aux;
diff --git a/gcc/hsa-gen.c b/gcc/hsa-gen.c
index 4679bb5..51160f5 100644
--- a/gcc/hsa-gen.c
+++ b/gcc/hsa-gen.c
@@ -82,7 +82,6 @@  static pool_allocator<hsa_insn_basic> *hsa_allocp_inst_basic;
 static pool_allocator<hsa_insn_phi> *hsa_allocp_inst_phi;
 static pool_allocator<hsa_insn_mem> *hsa_allocp_inst_mem;
 static pool_allocator<hsa_insn_atomic> *hsa_allocp_inst_atomic;
-static pool_allocator<hsa_insn_addr> *hsa_allocp_inst_addr;
 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;
@@ -98,6 +97,42 @@  static vec <hsa_op_reg *> hsa_list_operand_reg;
 static vec <hsa_insn_call_block *> hsa_list_insn_call_block;
 static vec <hsa_insn_call *> hsa_list_insn_call;
 
+/* Constructor of class representing global HSA function/kernel information and
+   state.  */
+
+/* TODO: Move more initialization here. */
+
+hsa_function_representation::hsa_function_representation ()
+  : prologue (ENTRY_BLOCK_PTR_FOR_FN (cfun), 0)
+{
+  name = NULL;
+  input_args_count = 0;
+  reg_count = 0;
+  input_args = NULL;
+  output_arg = NULL;
+
+  int sym_init_len = (vec_safe_length (cfun->local_decls) / 2) + 1;;
+  local_symbols = new hash_table <hsa_noop_symbol_hasher> (sym_init_len);
+  spill_symbols = vNULL;
+  hbb_count = 1;        /* 0 is for prologue.  */
+  in_ssa = true;	/* We start in SSA.  */
+  kern_p = false;
+}
+
+/* Destructor of class holding function/kernel-wide informaton and state.  */
+
+hsa_function_representation::~hsa_function_representation ()
+{
+  delete local_symbols;
+  free (input_args);
+  free (output_arg);
+  /* Kernel names are deallocated at the end of BRIG output when deallocating
+     hsa_decl_kernel_mapping.  */
+  if (!kern_p)
+    free (name);
+  spill_symbols.release ();
+}
+
 /* Allocate HSA structures that we need only while generating with this.  */
 
 static void
@@ -122,8 +157,6 @@  hsa_init_data_for_cfun ()
     = new pool_allocator<hsa_insn_mem> ("HSA memory instructions", 32);
   hsa_allocp_inst_atomic
     = new pool_allocator<hsa_insn_atomic> ("HSA atomic instructions", 32);
-  hsa_allocp_inst_addr
-    = new pool_allocator<hsa_insn_addr> ("HSA address instructions", 32);
   hsa_allocp_inst_seg
     = new pool_allocator<hsa_insn_seg> ("HSA segment conversion instructions",
 					16);
@@ -141,13 +174,8 @@  hsa_init_data_for_cfun ()
   sym_init_len = (vec_safe_length (cfun->local_decls) / 2) + 1;
   hsa_allocp_symbols = new pool_allocator<hsa_symbol> ("HSA symbols",
 						       sym_init_len);
-  memset (&hsa_cfun, 0, sizeof (hsa_cfun));
-  hsa_cfun.prologue.label_ref.kind = BRIG_KIND_OPERAND_CODE_REF;
-  hsa_cfun.local_symbols
-    = new hash_table <hsa_noop_symbol_hasher> (sym_init_len);
-  hsa_cfun.reg_count = 0;
-  hsa_cfun.hbb_count = 1;       /* 0 is for prologue.  */
-  hsa_cfun.in_ssa = true;	/* We start in SSA.  */
+
+  hsa_cfun = new hsa_function_representation ();
 }
 
 /* Deinitialize HSA subsystem and free all allocated memory.  */
@@ -160,8 +188,7 @@  hsa_deinit_data_for_cfun (void)
   FOR_EACH_BB_FN (bb, cfun)
     if (bb->aux)
       {
-	BITMAP_FREE (hsa_bb_for_bb (bb)->livein);
-	BITMAP_FREE (hsa_bb_for_bb (bb)->liveout);
+	hsa_bb_for_bb (bb)->~hsa_bb ();
 	bb->aux = NULL;
       }
 
@@ -190,23 +217,15 @@  hsa_deinit_data_for_cfun (void)
   delete hsa_allocp_inst_phi;
   delete hsa_allocp_inst_atomic;
   delete hsa_allocp_inst_mem;
-  delete hsa_allocp_inst_addr;
   delete hsa_allocp_inst_seg;
   delete hsa_allocp_inst_cmp;
   delete hsa_allocp_inst_br;
   delete hsa_allocp_inst_call;
   delete hsa_allocp_inst_call_block;
   delete hsa_allocp_bb;
-
   delete hsa_allocp_symbols;
-  delete hsa_cfun.local_symbols;
-  free (hsa_cfun.input_args);
-  free (hsa_cfun.output_arg);
-  /* Kernel names are deallocated at the end of BRIG output when deallocating
-     hsa_decl_kernel_mapping.  */
-  if (!hsa_cfun.kern_p)
-    free (hsa_cfun.name);
-  hsa_cfun.spill_symbols.release();
+
+  delete hsa_cfun;
 }
 
 /* Return the type which holds addresses in the given SEGMENT.  */
@@ -498,7 +517,7 @@  get_symbol_for_decl (tree decl)
     }
   else
     {
-      slot = hsa_cfun.local_symbols->find_slot (&dummy, INSERT);
+      slot = hsa_cfun->local_symbols->find_slot (&dummy, INSERT);
       gcc_checking_assert (slot);
       if (*slot)
 	return *slot;
@@ -528,26 +547,69 @@  hsa_get_spill_symbol (BrigType16_t type)
   sym->segment = BRIG_SEGMENT_SPILL;
   sym->linkage = BRIG_LINKAGE_FUNCTION;
   sym->type = type;
-  hsa_cfun.spill_symbols.safe_push(sym);
+  hsa_cfun->spill_symbols.safe_push(sym);
   return sym;
 }
 
-/* Allocate and clear a hsa_op_immed and set it to TREE_VAL.  */
+/* Constructor of the ancetor if all operands.  K is BRIG kind that identified
+   what the operator is.  */
+
+hsa_op_base::hsa_op_base (BrigKind16_t k) : next(0), brig_op_offset (0), kind (k)
+{
+}
+
+/* Constructor of ancestor of all operands which have a type.  K is BRIG kind
+   that identified what the operator is.  T is the type of the operator.  */
 
-static hsa_op_immed *
-hsa_alloc_immed_op (tree tree_val)
+hsa_op_with_type::hsa_op_with_type (BrigKind16_t k, BrigType16_t t)
+  : hsa_op_base (k), type (t)
 {
-  hsa_op_immed *imm = hsa_allocp_operand_immed->allocate ();
+}
+
+/* Constructor of class representing HSA immediate values.  TREE_VAL is the
+   tree representation of the immediate value. */
 
+hsa_op_immed::hsa_op_immed (tree tree_val)
+  : hsa_op_with_type (BRIG_KIND_OPERAND_CONSTANT_BYTES,
+		      hsa_type_for_scalar_tree_type (TREE_TYPE (tree_val),
+						     true)),
+    value (tree_val)
+{
   gcc_checking_assert (is_gimple_min_invariant (tree_val)
 		       && !POINTER_TYPE_P (TREE_TYPE (tree_val)));
+}
+
+/* New operator to allocate immediate operands from pool alloc.  */
+
+void *
+hsa_op_immed::operator new (size_t)
+{
+  return hsa_allocp_operand_immed->allocate ();
+}
 
-  memset (imm, 0 , sizeof (hsa_op_immed));
-  imm->kind = BRIG_KIND_OPERAND_CONSTANT_BYTES;
-  imm->type = hsa_type_for_scalar_tree_type (TREE_TYPE (tree_val), true);
-  imm->value = tree_val;
+/* Constructor of class representing HSA rgisters and pseudo-registers.  T is
+   the BRIG type fo the new register.  */
 
-  return imm;
+hsa_op_reg::hsa_op_reg (BrigType16_t t)
+  : hsa_op_with_type (BRIG_KIND_OPERAND_REGISTER, t)
+{
+  gimple_ssa = NULL_TREE;
+  def_insn = NULL;
+  spill_sym = NULL;
+  order = hsa_cfun->reg_count++;
+  lr_begin = lr_end = 0;
+  reg_class = 0;
+  hard_num = 0;
+
+  hsa_list_operand_reg.safe_push (this);
+}
+
+/* New operator to allocate immediate operands from pool alloc.  */
+
+void *
+hsa_op_reg::operator new (size_t)
+{
+  return hsa_allocp_operand_reg->allocate ();
 }
 
 /* Verify register operand.  */
@@ -566,55 +628,52 @@  hsa_op_reg::verify ()
 			   && SSA_NAME_IS_DEFAULT_DEF (gimple_ssa)));
 }
 
-/* Allocate, clear and return a hsa_op_reg.  */
+/* set up a new address operand consisting of base symbol SYM, register R and
+   immediate OFFSET.  If the machine model is not large and offset is 64 bit,
+   the upper, 32 bits have to be zero.  */
 
-static hsa_op_reg *
-hsa_alloc_reg_op (void)
+hsa_op_address::hsa_op_address (hsa_symbol *sym, hsa_op_reg *r,
+				HOST_WIDE_INT offset)
+  : hsa_op_base (BRIG_KIND_OPERAND_ADDRESS)
 {
-  hsa_op_reg *hreg;
-
-  hreg = hsa_allocp_operand_reg->allocate ();
-  hsa_list_operand_reg.safe_push (hreg);
-  memset (hreg, 0, sizeof (hsa_op_reg));
-  hreg->kind = BRIG_KIND_OPERAND_REGISTER;
-  hreg->order = hsa_cfun.reg_count++;
-  return hreg;
+  symbol = sym;
+  reg = r;
+  imm_offset = offset;
 }
 
-/* Allocate and set up a new address operand consisting of base symbol SYM,
-   register REG and immediate OFFSET.  If the machine model is not large and
-   offset is 64 bit, the upper, 32 bits have to be zero.  */
+/* New operator to allocate address operands from pool alloc.  */
 
-static hsa_op_address *
-hsa_alloc_addr_op (hsa_symbol *sym, hsa_op_reg *reg, HOST_WIDE_INT offset)
+void *
+hsa_op_address::operator new (size_t)
 {
-  hsa_op_address *addr;
+  return hsa_allocp_operand_address->allocate ();
+}
+
+/* Constructor of an operand referring to HSAIL code.  */
 
-  addr = hsa_allocp_operand_address->allocate ();
-  memset (addr, 0, sizeof (hsa_op_address));
-  addr->kind = BRIG_KIND_OPERAND_ADDRESS;
-  addr->symbol = sym;
-  addr->reg = reg;
-  addr->imm_offset = offset;
-  return addr;
+hsa_op_code_ref::hsa_op_code_ref () : hsa_op_base (BRIG_KIND_OPERAND_CODE_REF)
+{
+  directive_offset = 0;
 }
 
-/* Allocate and set up a new code list operands with given number
-   of ELEMENTS.  */
+/* Constructor of an operand representing a code list.  Set it up so that it
+   can contain ELEMENTS number of elements.  */
 
-static hsa_op_code_list *
-hsa_alloc_code_list_op (unsigned elements)
+hsa_op_code_list::hsa_op_code_list (unsigned elements)
+  : hsa_op_base (BRIG_KIND_OPERAND_CODE_LIST)
 {
-  hsa_op_code_list *list;
-  list = hsa_allocp_operand_code_list->allocate ();
-  hsa_list_operand_code_list.safe_push (list);
+  offsets.create (1);
+  offsets.safe_grow_cleared (elements);
+
+  hsa_list_operand_code_list.safe_push (this);
+}
 
-  memset (list, 0, sizeof (hsa_op_code_list));
-  list->kind = BRIG_KIND_OPERAND_CODE_LIST;
-  list->offsets.create (1);
-  list->offsets.safe_grow_cleared (elements);
+/* New operator to allocate code list operands.  */
 
-  return list;
+void *
+hsa_op_code_list::operator new (size_t)
+{
+  return hsa_allocp_operand_code_list->allocate ();
 }
 
 /* Lookup or create a HSA pseudo register for a given gimple SSA name.  */
@@ -628,8 +687,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 = hsa_alloc_reg_op ();
-  hreg->type = hsa_type_for_scalar_tree_type (TREE_TYPE (ssa), true);
+  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;
 
@@ -642,7 +700,7 @@  hsa_reg_for_gimple_ssa (tree ssa, vec <hsa_op_reg_p> ssa_map)
 static inline void
 set_reg_def (hsa_op_reg *reg, hsa_insn_basic *insn)
 {
-  if (hsa_cfun.in_ssa)
+  if (hsa_cfun->in_ssa)
     {
       gcc_checking_assert (!reg->def_insn);
       reg->def_insn = insn;
@@ -651,125 +709,209 @@  set_reg_def (hsa_op_reg *reg, hsa_insn_basic *insn)
     reg->def_insn = NULL;
 }
 
-/* Allocate, clear and return a new basic instruction.  Note that it cannot set
-   any opcode.  */
+/* Constructor of the class which is the bases of all instructions and directly
+   represents the most basic ones.  NOPS is the number of operands that the
+   operand vector will contain (and which will be cleared).  OP is the opcode
+   of the instruction.  This constructor does not set type.  */
 
-static hsa_insn_basic *
-hsa_alloc_basic_insn (void)
+hsa_insn_basic::hsa_insn_basic (unsigned nops, int opc)
 {
-  hsa_insn_basic *hin;
+  opcode = opc;
+
+  prev = next = NULL;
+  bb = NULL;
+  number = 0;
+  type = BRIG_TYPE_NONE;
 
-  hin = hsa_allocp_inst_basic->allocate ();
-  memset (hin, 0, sizeof (hsa_insn_basic));
-  return hin;
+  if (nops > 0)
+    operands.safe_grow_cleared (nops);
 }
 
-/* Allocate, clear and return a memory instruction structure.  */
+/* Constructor of the class which is the bases of all instructions and directly
+   represents the most basic ones.  NOPS is the number of operands that the
+   operand vector will contain (and which will be cleared).  OPC is the opcode
+   of the instruction, T is the type of the instruction.  */
 
-static hsa_insn_mem *
-hsa_alloc_mem_insn (void)
+hsa_insn_basic::hsa_insn_basic (unsigned nops, int opc, BrigType16_t t)
 {
-  hsa_insn_mem *mem;
+  opcode = opc;
+  type = t;
 
-  mem = hsa_allocp_inst_mem->allocate ();
-  memset (mem, 0, sizeof (hsa_insn_mem));
-  return mem;
+  prev = next = NULL;
+  bb = NULL;
+  number = 0;
+
+  if (nops > 0)
+    operands.safe_grow_cleared (nops);
 }
 
-/* Allocate, clear and return a memory instruction structure.  */
+/* New operator for the most basic instructions.  */
 
-static hsa_insn_atomic *
-hsa_alloc_atomic_insn (void)
+void *
+hsa_insn_basic::operator new (size_t)
 {
-  hsa_insn_atomic *ret;
+  return hsa_allocp_inst_basic->allocate ();
+}
 
-  ret = hsa_allocp_inst_atomic->allocate ();
-  memset (ret, 0, sizeof (hsa_insn_atomic));
-  return ret;
+/* Constructor of an instruction representing a PHI node.  NOPS is the number
+   of operands (equal to the number of predecessors).  */
+
+hsa_insn_phi::hsa_insn_phi (unsigned nops)
+  : hsa_insn_basic (nops, HSA_OPCODE_PHI)
+{
 }
 
-/* Allocate, clear and return an address instruction structure.  */
+/* Operator new for an instruction representing an HSA phi node.  */
 
-static hsa_insn_addr *
-hsa_alloc_addr_insn (void)
+void *
+hsa_insn_phi::operator new (size_t)
 {
-  hsa_insn_addr *addr;
+  return hsa_allocp_inst_phi->allocate ();
+}
+
+/* Constructor of clas representing instruction for conditional jump, CTRL is
+   the control register deterining whether the jump will be carried out, the
+   new instruction is automatically added to its uses list.  */
 
-  addr = hsa_allocp_inst_addr->allocate ();
-  memset (addr, 0, sizeof (hsa_insn_addr));
-  return addr;
+hsa_insn_br::hsa_insn_br (hsa_op_reg *ctrl) : hsa_insn_basic (1, BRIG_OPCODE_CBR)
+{
+  width =  BRIG_WIDTH_1;
+  operands[0] = ctrl;
+  ctrl->uses.safe_push (this);
 }
 
-/* Allocate, clear and return a segment conversion instruction structure.  */
+/* New operator for jumps and contitional jumps.  */
+void *
+hsa_insn_br::operator new (size_t)
+{
+  return hsa_allocp_inst_br->allocate ();
+}
 
-static hsa_insn_seg *
-hsa_alloc_seg_insn (void)
+/* Constructor of comparison instructin.  CMP is the comparison operation and T
+   is the result type.  */
+
+hsa_insn_cmp::hsa_insn_cmp (BrigCompareOperation8_t cmp, BrigType16_t t)
+  : hsa_insn_basic (3 , BRIG_OPCODE_CMP, t)
 {
-  hsa_insn_seg *seg;
+  compare = cmp;
+}
 
-  seg = hsa_allocp_inst_seg->allocate ();
-  memset (seg, 0, sizeof (hsa_insn_seg));
-  return seg;
+/* New operator for comparison instruction representation class.  */
+
+void *
+hsa_insn_cmp::operator new (size_t)
+{
+  return hsa_allocp_inst_cmp->allocate ();
 }
 
-/* Allocate, clear and return a comparison instruction structure.  Also sets the
-   opcode.  */
+/* Constructor of classes representing memory accesses.  OPC is the opcode (must
+   be BRIG_OPCODE_ST or BRIG_OPCODE_LD) and T is the type.  */
 
-static hsa_insn_cmp *
-hsa_alloc_cmp_insn (void)
+hsa_insn_mem::hsa_insn_mem (int opc, BrigType16_t t)
+  : hsa_insn_basic (2, opc, t)
 {
-  hsa_insn_cmp *cmp;
+  gcc_checking_assert (opc == BRIG_OPCODE_LD || opc == BRIG_OPCODE_ST);
+  equiv_class = 0;
+  memoryorder = BRIG_MEMORY_ORDER_NONE;
+  memoryscope = BRIG_MEMORY_SCOPE_NONE;
+}
+
+/* Constructor for descendants allowing different opcodes and number of
+   operands, it passes its arguments directly to hsa_insn_basic
+   constructor.  */
 
-  cmp = hsa_allocp_inst_cmp->allocate ();
-  memset (cmp, 0, sizeof (hsa_insn_cmp));
-  cmp->opcode = BRIG_OPCODE_CMP;
-  return cmp;
+hsa_insn_mem::hsa_insn_mem (unsigned nops, int opc, BrigType16_t t)
+  : hsa_insn_basic (nops, opc, t)
+{
+  equiv_class = 0;
+  memoryorder = BRIG_MEMORY_ORDER_NONE;
+  memoryscope = BRIG_MEMORY_SCOPE_NONE;
 }
 
-/* Allocate, clear and return a conditional jump instruction structure.  Also
-   sets the opcode.  CTRL is the controlling register.  */
+/* New operator of memory access instruction representation.  */
 
-static hsa_insn_br *
-hsa_build_cbr_insn (hsa_op_reg *ctrl)
+void *
+hsa_insn_mem::operator new (size_t)
 {
-  hsa_insn_br *cbr;
+  return hsa_allocp_inst_mem->allocate ();
+}
+
+/* Constructor of class representing atomic instructions. OPC is the prinicpa;
+   opcode, aop is the specific atomic operation opcode.  T is the type of the
+   instruction.  */
 
-  cbr = hsa_allocp_inst_br->allocate ();
-  memset (cbr, 0, sizeof (hsa_insn_br));
-  cbr->opcode = BRIG_OPCODE_CBR;
-  cbr->type = BRIG_TYPE_NONE;
-  cbr->width =  BRIG_WIDTH_1;
-  cbr->operands[0] = ctrl;
-  ctrl->uses.safe_push (cbr);
-  return cbr;
+hsa_insn_atomic::hsa_insn_atomic (int opc, enum BrigAtomicOperation aop,
+				  BrigType16_t t)
+  : hsa_insn_mem (4, opc, t)
+{
+  gcc_checking_assert (opc == BRIG_OPCODE_ATOMICNORET ||
+		       opc == BRIG_OPCODE_ATOMIC);
+  atomicop = aop;
 }
 
-/* Allocate, clear and return a call instruction structure.  */
+/* New operator for class representing atomic instructions. */
 
-static hsa_insn_call *
-hsa_alloc_call_insn (void)
+void *
+hsa_insn_atomic::operator new (size_t)
 {
-  hsa_insn_call *call;
+  return hsa_allocp_inst_atomic->allocate ();
+}
 
-  call = hsa_allocp_inst_call->allocate ();
-  hsa_list_insn_call.safe_push (call);
-  memset (call, 0, sizeof (hsa_insn_call));
-  return call;
+/* Constructor of class representing segment conversion instructions.  OPC is
+   the opcode which must be either BRIG_OPCODE_STOF or BRIG_OPCODE_FTOS.  DESTT
+   and SRCT are destination and source types respectively, SEG is the segment
+   we are converting to or from.  */
+
+hsa_insn_seg::hsa_insn_seg (int opc, BrigType16_t destt, BrigType16_t srct,
+			    BrigSegment8_t seg)
+  : hsa_insn_basic (2, opc, destt)
+{
+  gcc_checking_assert (opc == BRIG_OPCODE_STOF || opc == BRIG_OPCODE_FTOS);
+  src_type = srct;
+  segment = seg;
 }
 
-/* Allocate, clear and return an argument block instruction structure.  */
+/* New operator for segment conversion instructions  */
 
-static hsa_insn_call_block *
-hsa_alloc_call_block_insn (void)
+void *
+hsa_insn_seg::operator new (size_t)
 {
-  hsa_insn_call_block *call_block;
+  return hsa_allocp_inst_seg->allocate ();
+}
+
+/* Constructor of class representing a call instruction.  CALLEE is the tree
+   representation of the function being called.  */
+
+hsa_insn_call::hsa_insn_call (tree callee) : hsa_insn_basic (0, BRIG_OPCODE_CALL)
+{
+  called_function = callee;
+  func.kind = BRIG_KIND_OPERAND_CODE_REF;
+  result_symbol = NULL;
+  result_symbol = NULL;
+  hsa_list_insn_call.safe_push (this);
+}
+
+/* Operator new for classes representing a call.  */
+
+void *
+hsa_insn_call::operator new (size_t)
+{
+  return hsa_allocp_inst_call->allocate ();
+}
 
-  call_block = hsa_allocp_inst_call_block->allocate ();
-  hsa_list_insn_call_block.safe_push (call_block);
-  memset (call_block, 0, sizeof (hsa_insn_call_block));
+/* 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)
+{
+  hsa_list_insn_call_block.safe_push (this);
+}
 
-  call_block->opcode = HSA_OPCODE_CALL_BLOCK;
-  return call_block;
+/* New operator for classes representing HSAIL call blocks.  */
+void *
+hsa_insn_call_block::operator new (size_t)
+{
+  return hsa_allocp_inst_call_block->allocate ();
 }
 
 /* Append HSA instruction INSN to basic block HBB.  */
@@ -836,11 +978,8 @@  hsa_reg_for_gimple_ssa_reqtype (tree ssa, vec <hsa_op_reg_p> ssa_map,
   hsa_op_reg *reg = hsa_reg_for_gimple_ssa (ssa, ssa_map);
   if (hsa_needs_cvt (reqtype, reg->type))
     {
-      hsa_op_reg *converted = hsa_alloc_reg_op ();
-      converted->type = reqtype;
-      hsa_insn_basic *insn = hsa_alloc_basic_insn ();
-      insn->opcode = BRIG_OPCODE_CVT;
-      insn->type = reqtype;
+      hsa_op_reg *converted = new hsa_op_reg (reqtype);
+      hsa_insn_basic *insn = new hsa_insn_basic (2, BRIG_OPCODE_CVT, reqtype);
       insn->operands[0] = converted;
       insn->operands[1] = reg;
       reg->uses.safe_push (insn);
@@ -881,7 +1020,7 @@  gen_address_calculation (tree exp, hsa_bb *hbb, vec <hsa_op_reg_p> ssa_map,
 
     case INTEGER_CST:
       {
-       hsa_op_immed *imm = hsa_alloc_immed_op (exp);
+       hsa_op_immed *imm = new hsa_op_immed (exp);
        if (addrtype != imm->type)
 	 {
 	   gcc_assert (hsa_type_bit_size (addrtype)
@@ -903,13 +1042,10 @@  gen_address_calculation (tree exp, hsa_bb *hbb, vec <hsa_op_reg_p> ssa_map,
       gcc_unreachable ();
     }
 
-  hsa_op_reg *res = hsa_alloc_reg_op ();
-  res->type = addrtype;
-  hsa_insn_basic *insn = hsa_alloc_basic_insn ();
-  insn->opcode = opcode;
+  hsa_op_reg *res = new hsa_op_reg (addrtype);
+  hsa_insn_basic *insn = new hsa_insn_basic (3, opcode, addrtype);
   insn->operands[0] = res;
   set_reg_def (res, insn);
-  insn->type = addrtype;
 
   hsa_op_with_type *op1 = gen_address_calculation (TREE_OPERAND (exp, 0), hbb,
 						   ssa_map, addrtype, insn);
@@ -934,14 +1070,11 @@  add_addr_regs_if_needed (hsa_op_reg *r1, hsa_op_reg *r2, hsa_bb *hbb)
   if (!r1)
     return r2;
 
-  hsa_op_reg *res = hsa_alloc_reg_op ();
+  hsa_op_reg *res = new hsa_op_reg (r1->type);
   gcc_assert (!hsa_needs_cvt (r1->type, r2->type));
-  res->type = r1->type;
-  hsa_insn_basic *insn = hsa_alloc_basic_insn ();
-  insn->opcode = BRIG_OPCODE_ADD;
+  hsa_insn_basic *insn = new hsa_insn_basic (3, BRIG_OPCODE_ADD, res->type);
   insn->operands[0] = res;
   set_reg_def (res, insn);
-  insn->type = res->type;
   insn->operands[1] = r1;
   r1->uses.safe_push (insn);
   insn->operands[2] = r2;
@@ -1075,16 +1208,14 @@  gen_hsa_addr (tree ref, hsa_bb *hbb, vec <hsa_op_reg_p> ssa_map)
 						addrtype);
 	  if (TMR_STEP (ref) && !integer_onep (TMR_STEP (ref)))
 	    {
-	      disp1 = hsa_alloc_reg_op ();
-	      disp1->type = addrtype;
-	      hsa_insn_basic *insn = hsa_alloc_basic_insn ();
-	      insn->type = addrtype;
-	      insn->opcode = BRIG_OPCODE_MUL;
+	      disp1 = new hsa_op_reg (addrtype);
+	      hsa_insn_basic *insn = new hsa_insn_basic (3, BRIG_OPCODE_MUL,
+							 addrtype);
 	      insn->operands[0] = disp1;
 	      set_reg_def (disp1, insn);
 	      insn->operands[1] = idx;
 	      idx->uses.safe_push (insn);
-	      insn->operands[2] = hsa_alloc_immed_op (TMR_STEP (ref));
+	      insn->operands[2] = new hsa_op_immed (TMR_STEP (ref));
 	      hsa_append_insn (hbb, insn);
 	    }
 	  else
@@ -1127,7 +1258,7 @@  gen_hsa_addr (tree ref, hsa_bb *hbb, vec <hsa_op_reg_p> ssa_map)
 out:
   HOST_WIDE_INT hwi_offset = offset.to_shwi ();
 
-  return hsa_alloc_addr_op (symbol, reg, hwi_offset);
+  return new hsa_op_address (symbol, reg, hwi_offset);
 }
 
 /* Generate HSA address for a function call argument of given TYPE.
@@ -1152,7 +1283,7 @@  gen_hsa_addr_for_arg (tree tree_type, int index)
       sym->name_number = index;
     }
 
-  return hsa_alloc_addr_op (sym, NULL, 0);
+  return new hsa_op_address (sym, NULL, 0);
 }
 
 /* Generate HSA instructions that calculate address of VAL including all
@@ -1165,13 +1296,12 @@  gen_hsa_addr_insns (tree val, hsa_op_reg *dest, hsa_bb *hbb,
 		    vec <hsa_op_reg_p> ssa_map)
 {
   hsa_op_address *addr;
-  hsa_insn_addr *insn = hsa_alloc_addr_insn ();
+  hsa_insn_basic *insn = new hsa_insn_basic (2, BRIG_OPCODE_LDA);
 
   gcc_assert (dest->type == hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT));
   if (TREE_CODE (val) == ADDR_EXPR)
     val = TREE_OPERAND (val, 0);
   addr = gen_hsa_addr (val, hbb, ssa_map);
-  insn->opcode = BRIG_OPCODE_LDA;
   insn->operands[1] = addr;
   if (addr->reg)
     addr->reg->uses.safe_push (insn);
@@ -1179,19 +1309,17 @@  gen_hsa_addr_insns (tree val, hsa_op_reg *dest, hsa_bb *hbb,
     {
       /* LDA produces segment-relative address, we need to convert
 	 it to the flat one.  */
-      hsa_op_reg *tmp = hsa_alloc_reg_op ();
-      hsa_insn_seg *seg = hsa_alloc_seg_insn ();
+      hsa_op_reg *tmp;
+      tmp = new hsa_op_reg (hsa_get_segment_addr_type (addr->symbol->segment));
+      hsa_insn_seg *seg;
+      seg = new hsa_insn_seg (BRIG_OPCODE_STOF,
+			      hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT),
+			      tmp->type, addr->symbol->segment);
 
       insn->operands[0] = tmp;
       set_reg_def (tmp, insn);
-      tmp->type = hsa_get_segment_addr_type (addr->symbol->segment);
       insn->type = tmp->type;
       hsa_append_insn (hbb, insn);
-
-      seg->opcode = BRIG_OPCODE_STOF;
-      seg->type = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
-      seg->segment = addr->symbol->segment;
-      seg->src_type = tmp->type;
       seg->operands[0] = dest;
       seg->operands[1] = tmp;
       set_reg_def (dest, seg);
@@ -1222,11 +1350,10 @@  hsa_reg_or_immed_for_gimple_op (tree op, hsa_bb *hbb,
   if (TREE_CODE (op) == SSA_NAME)
     tmp = hsa_reg_for_gimple_ssa (op, ssa_map);
   else if (!POINTER_TYPE_P (TREE_TYPE (op)))
-    return hsa_alloc_immed_op (op);
+    return new hsa_op_immed (op);
   else
     {
-      tmp = hsa_alloc_reg_op ();
-      tmp->type = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
+      tmp = new hsa_op_reg (hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT));
       gen_hsa_addr_insns (op, tmp, hbb, ssa_map);
     }
   if (new_use)
@@ -1240,10 +1367,7 @@  hsa_reg_or_immed_for_gimple_op (tree op, hsa_bb *hbb,
 void
 hsa_build_append_simple_mov (hsa_op_reg *dest, hsa_op_base *src, hsa_bb *hbb)
 {
-  hsa_insn_basic *insn = hsa_alloc_basic_insn ();
-
-  insn->opcode = BRIG_OPCODE_MOV;
-  insn->type = dest->type;
+  hsa_insn_basic *insn = new hsa_insn_basic (2, BRIG_OPCODE_MOV, dest->type);
   insn->operands[0] = dest;
   insn->operands[1] = src;
   if (hsa_op_reg *sreg = dyn_cast <hsa_op_reg *> (src))
@@ -1291,7 +1415,7 @@  gen_hsa_insns_for_load (hsa_op_reg *dest, tree rhs, tree type, hsa_bb *hbb,
 	}
       else
 	{
-	  hsa_op_immed *imm = hsa_alloc_immed_op (rhs);
+	  hsa_op_immed *imm = new hsa_op_immed (rhs);
 	  hsa_build_append_simple_mov (dest, imm, hbb);
 	}
     }
@@ -1301,13 +1425,11 @@  gen_hsa_insns_for_load (hsa_op_reg *dest, tree rhs, tree type, hsa_bb *hbb,
     {
       /* Load from memory.  */
       hsa_op_address *addr;
-      hsa_insn_mem *mem = hsa_alloc_mem_insn ();
-
-      addr = gen_hsa_addr (rhs, hbb, ssa_map);
-      mem->opcode = BRIG_OPCODE_LD;
+      BrigType16_t mtype;
       /* Not dest->type, that's possibly extended.  */
-      mem->type = mem_type_for_type (hsa_type_for_scalar_tree_type (type,
-								    false));
+      mtype = mem_type_for_type (hsa_type_for_scalar_tree_type (type, false));
+      hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, mtype);
+      addr = gen_hsa_addr (rhs, hbb, ssa_map);
       mem->operands[0] = dest;
       mem->operands[1] = addr;
       set_reg_def (dest, mem);
@@ -1328,15 +1450,14 @@  static void
 gen_hsa_insns_for_store (tree lhs, hsa_op_base *src, hsa_bb *hbb,
 			 vec <hsa_op_reg_p> ssa_map)
 {
-  hsa_insn_mem *mem = hsa_alloc_mem_insn ();
+  BrigType16_t mtype;
+  mtype = mem_type_for_type (hsa_type_for_scalar_tree_type (TREE_TYPE (lhs),
+							    false));
+  hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, mtype);
   hsa_op_address *addr;
-
   addr = gen_hsa_addr (lhs, hbb, ssa_map);
-  mem->opcode = BRIG_OPCODE_ST;
   if (hsa_op_reg *reg = dyn_cast <hsa_op_reg *> (src))
     reg->uses.safe_push (mem);
-  mem->type = mem_type_for_type (hsa_type_for_scalar_tree_type (TREE_TYPE (lhs),
-								false));
 
   /* XXX The HSAIL disasm has another constraint: if the source
      is an immediate then it must match the destination type.  If
@@ -1420,13 +1541,10 @@  hsa_op_reg *
 hsa_spill_in (hsa_insn_basic *insn, hsa_op_reg *spill_reg, hsa_op_reg **ptmp2)
 {
   hsa_symbol *spill_sym = spill_reg->spill_sym;
-  hsa_insn_mem *mem = hsa_alloc_mem_insn ();
-  hsa_op_reg *reg = hsa_alloc_reg_op ();
-  hsa_op_address *addr = hsa_alloc_addr_op (spill_sym, NULL, 0);
+  hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, spill_sym->type);
+  hsa_op_reg *reg = new hsa_op_reg (spill_sym->type);
+  hsa_op_address *addr = new hsa_op_address (spill_sym, NULL, 0);
 
-  mem->opcode = BRIG_OPCODE_LD;
-  mem->type = spill_sym->type;
-  reg->type = spill_sym->type;
   mem->operands[0] = reg;
   mem->operands[1] = addr;
   hsa_insert_insn_before (mem, insn);
@@ -1436,14 +1554,11 @@  hsa_spill_in (hsa_insn_basic *insn, hsa_op_reg *spill_reg, hsa_op_reg **ptmp2)
     {
       hsa_insn_basic *cvtinsn;
       *ptmp2 = reg;
-      reg = hsa_alloc_reg_op ();
-      reg->type = spill_reg->type;
+      reg = new hsa_op_reg (spill_reg->type);
 
-      cvtinsn = hsa_alloc_basic_insn ();
-      cvtinsn->opcode = BRIG_OPCODE_CVT;
+      cvtinsn = new hsa_insn_basic (2, BRIG_OPCODE_CVT, reg->type);
       cvtinsn->operands[0] = reg;
       cvtinsn->operands[1] = *ptmp2;
-      cvtinsn->type = reg->type;
 
       hsa_insert_insn_before (cvtinsn, insn);
     }
@@ -1459,9 +1574,9 @@  hsa_op_reg *
 hsa_spill_out (hsa_insn_basic *insn, hsa_op_reg *spill_reg, hsa_op_reg **ptmp2)
 {
   hsa_symbol *spill_sym = spill_reg->spill_sym;
-  hsa_insn_mem *mem = hsa_alloc_mem_insn ();
-  hsa_op_reg *reg = hsa_alloc_reg_op ();
-  hsa_op_address *addr = hsa_alloc_addr_op (spill_sym, NULL, 0);
+  hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, spill_sym->type);
+  hsa_op_reg *reg = new hsa_op_reg (spill_sym->type);
+  hsa_op_address *addr = new hsa_op_address (spill_sym, NULL, 0);
   hsa_op_reg *returnreg;
 
   *ptmp2 = NULL;
@@ -1469,29 +1584,21 @@  hsa_spill_out (hsa_insn_basic *insn, hsa_op_reg *spill_reg, hsa_op_reg **ptmp2)
   if (spill_reg->type == BRIG_TYPE_B1)
     {
       hsa_insn_basic *cvtinsn;
-      *ptmp2 = hsa_alloc_reg_op ();
-      (*ptmp2)->type = spill_sym->type;
+      *ptmp2 = new hsa_op_reg (spill_sym->type);
       reg->type = spill_reg->type;
 
-      cvtinsn = hsa_alloc_basic_insn ();
-      cvtinsn->opcode = BRIG_OPCODE_CVT;
+      cvtinsn = new hsa_insn_basic (2, BRIG_OPCODE_CVT, spill_sym->type);
       cvtinsn->operands[0] = *ptmp2;
       cvtinsn->operands[1] = returnreg;
-      cvtinsn->type = (*ptmp2)->type;
 
       hsa_append_insn_after (cvtinsn, insn);
       insn = cvtinsn;
       reg = *ptmp2;
     }
 
-  mem->opcode = BRIG_OPCODE_ST;
-  mem->type = spill_sym->type;
-  reg->type = spill_sym->type;
   mem->operands[0] = reg;
   mem->operands[1] = addr;
-
   hsa_append_insn_after (mem, insn);
-
   return returnreg;
 }
 
@@ -1506,37 +1613,37 @@  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)
 {
-  hsa_insn_cmp *cmp = hsa_alloc_cmp_insn ();
+  BrigCompareOperation8_t compare;
 
   switch (code)
     {
     case LT_EXPR:
-      cmp->compare = BRIG_COMPARE_LT;
+      compare = BRIG_COMPARE_LT;
       break;
     case LE_EXPR:
-      cmp->compare = BRIG_COMPARE_LE;
+      compare = BRIG_COMPARE_LE;
       break;
     case GT_EXPR:
-      cmp->compare = BRIG_COMPARE_GT;
+      compare = BRIG_COMPARE_GT;
       break;
     case GE_EXPR:
-      cmp->compare = BRIG_COMPARE_GE;
+      compare = BRIG_COMPARE_GE;
       break;
     case EQ_EXPR:
-      cmp->compare = BRIG_COMPARE_EQ;
+      compare = BRIG_COMPARE_EQ;
       break;
     case NE_EXPR:
-      cmp->compare = BRIG_COMPARE_NE;
+      compare = BRIG_COMPARE_NE;
       break;
     default:
       sorry ("Support for HSA does not implement comparison tree code %s\n",
 	     get_tree_code_name (code));
       return;
     }
-  cmp->type = dest->type;
+
+  hsa_insn_cmp *cmp = new hsa_insn_cmp (compare, dest->type);
   cmp->operands[0] = dest;
   set_reg_def (dest, cmp);
-
   cmp->operands[1] = hsa_reg_or_immed_for_gimple_op (lhs, hbb, ssa_map, cmp);
   cmp->operands[2] = hsa_reg_or_immed_for_gimple_op (rhs, hbb, ssa_map, cmp);
   hsa_append_insn (hbb, cmp);
@@ -1550,8 +1657,6 @@  static void
 gen_hsa_insns_for_operation_assignment (gimple assign, hsa_bb *hbb,
 					vec <hsa_op_reg_p> ssa_map)
 {
-  hsa_insn_basic *insn;
-  hsa_op_reg *dest;
   int opcode;
 
   switch (gimple_assign_rhs_code (assign))
@@ -1650,7 +1755,8 @@  gen_hsa_insns_for_operation_assignment (gimple assign, hsa_bb *hbb,
     case EQ_EXPR:
     case NE_EXPR:
       {
-	dest = hsa_reg_for_gimple_ssa (gimple_assign_lhs (assign), ssa_map);
+	hsa_op_reg *dest = hsa_reg_for_gimple_ssa (gimple_assign_lhs (assign),
+						   ssa_map);
 	gen_hsa_cmp_insn_from_gimple (gimple_assign_rhs_code (assign),
 				      gimple_assign_rhs1 (assign),
 				      gimple_assign_rhs2 (assign),
@@ -1665,13 +1771,28 @@  gen_hsa_insns_for_operation_assignment (gimple assign, hsa_bb *hbb,
       return;
     }
 
+  unsigned nops;
+  switch (get_gimple_rhs_class (gimple_expr_code (assign)))
+    {
+    case GIMPLE_TERNARY_RHS:
+      nops = 4;
+      break;
+    case GIMPLE_BINARY_RHS:
+      nops = 3;
+      break;
+    case GIMPLE_UNARY_RHS:
+      nops = 2;
+      break;
+    default:
+      gcc_unreachable ();
+    }
+
+  hsa_op_reg *dest = hsa_reg_for_gimple_ssa (gimple_assign_lhs (assign),
+					     ssa_map);
   /* FIXME: Allocate an instruction with modifiers if appropriate.  */
-  insn = hsa_alloc_basic_insn ();
-  insn->opcode = opcode;
-  dest = hsa_reg_for_gimple_ssa (gimple_assign_lhs (assign), ssa_map);
+  hsa_insn_basic *insn = new hsa_insn_basic (nops, opcode, dest->type);
   insn->operands[0] = dest;
   set_reg_def (dest, insn);
-  insn->type = dest->type;
 
   switch (get_gimple_rhs_class (gimple_expr_code (assign)))
     {
@@ -1722,16 +1843,15 @@  static void
 gen_hsa_insns_for_cond_stmt (gimple cond, hsa_bb *hbb,
 			     vec <hsa_op_reg_p> ssa_map)
 {
-  hsa_op_reg *ctrl = hsa_alloc_reg_op ();
+  hsa_op_reg *ctrl = new hsa_op_reg (BRIG_TYPE_B1);
   hsa_insn_br *cbr;
 
-  ctrl->type = BRIG_TYPE_B1;
   gen_hsa_cmp_insn_from_gimple (gimple_cond_code (cond),
 				gimple_cond_lhs (cond),
 				gimple_cond_rhs (cond),
 				ctrl, hbb, ssa_map);
 
-  cbr = hsa_build_cbr_insn (ctrl);
+  cbr = new hsa_insn_br (ctrl);
   hsa_append_insn (hbb, cbr);
 }
 
@@ -1744,27 +1864,21 @@  static void
 gen_hsa_insns_for_direct_call (gimple stmt, hsa_bb *hbb,
 			       vec <hsa_op_reg_p> ssa_map)
 {
-  hsa_insn_call *call_insn = hsa_alloc_call_insn ();
-  call_insn->opcode = BRIG_OPCODE_CALL;
-  call_insn->called_function = gimple_call_fndecl (stmt);
-  call_insn->func.kind = BRIG_KIND_OPERAND_CODE_REF;
-
-  hsa_insn_call_block *call_block_insn = hsa_alloc_call_block_insn ();
+  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 ();
 
   /* 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);
-      hsa_op_address *addr;
-      hsa_insn_mem *mem = hsa_alloc_mem_insn ();
+      BrigType16_t mtype = mem_type_for_type (hsa_type_for_scalar_tree_type
+					      (TREE_TYPE (parm), false));
+      hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, mtype);
       hsa_op_base *src = hsa_reg_or_immed_for_gimple_op (parm, hbb, ssa_map,
 							 mem);
-
+      hsa_op_address *addr;
       addr = gen_hsa_addr_for_arg (TREE_TYPE (parm), i);
-      mem->opcode = BRIG_OPCODE_ST;
-      mem->type = mem_type_for_type (hsa_type_for_scalar_tree_type
-				     (TREE_TYPE (parm), false));
       mem->operands[0] = src;
       mem->operands[1] = addr;
 
@@ -1774,7 +1888,7 @@  gen_hsa_insns_for_direct_call (gimple stmt, hsa_bb *hbb,
       call_insn->args_symbols.safe_push (addr->symbol);
     }
 
-  call_insn->args_code_list = hsa_alloc_code_list_op (args);
+  call_insn->args_code_list = new hsa_op_code_list (args);
 
   tree result_type = TREE_TYPE (TREE_TYPE (gimple_call_fndecl (stmt)));
 
@@ -1788,12 +1902,11 @@  gen_hsa_insns_for_direct_call (gimple stmt, hsa_bb *hbb,
 	 declaration for the result.  */
       if (result)
 	{
-	  result_insn = hsa_alloc_mem_insn ();
+	  BrigType16_t mtype = mem_type_for_type
+	    (hsa_type_for_scalar_tree_type (TREE_TYPE (result), false));
+	  result_insn = new hsa_insn_mem (BRIG_OPCODE_LD, mtype);
 	  hsa_op_reg *dst = hsa_reg_for_gimple_ssa (result, ssa_map);
 
-	  result_insn->opcode = BRIG_OPCODE_LD;
-	  result_insn->type = mem_type_for_type
-	    (hsa_type_for_scalar_tree_type (TREE_TYPE (result), false));
 	  result_insn->operands[0] = dst;
 	  result_insn->operands[1] = addr;
 	  set_reg_def (dst, result_insn);
@@ -1803,10 +1916,10 @@  gen_hsa_insns_for_direct_call (gimple stmt, hsa_bb *hbb,
 
       call_block_insn->output_arg = addr->symbol;
       call_insn->result_symbol = addr->symbol;
-      call_insn->result_code_list = hsa_alloc_code_list_op (1);
+      call_insn->result_code_list = new hsa_op_code_list (1);
     }
   else
-    call_insn->result_code_list = hsa_alloc_code_list_op (0);
+    call_insn->result_code_list = new hsa_op_code_list (0);
 
   call_block_insn->call_insn = call_insn;
 
@@ -1829,22 +1942,20 @@  gen_hsa_insns_for_return (greturn *stmt, hsa_bb *hbb,
   if (retval)
     {
       /* Store of return value.  */
-      hsa_insn_mem *mem = hsa_alloc_mem_insn ();
+      BrigType16_t mtype = mem_type_for_type
+	(hsa_type_for_scalar_tree_type (TREE_TYPE (retval), false));
+      hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, mtype);
       hsa_op_base *src = hsa_reg_or_immed_for_gimple_op (retval, hbb, ssa_map,
 							 mem);
 
-      hsa_op_address *addr = hsa_alloc_addr_op (hsa_cfun.output_arg, NULL, 0);
-      mem->opcode = BRIG_OPCODE_ST;
-      mem->type = mem_type_for_type
-	(hsa_type_for_scalar_tree_type (TREE_TYPE (retval), false));
+      hsa_op_address *addr = new hsa_op_address (hsa_cfun->output_arg, NULL, 0);
       mem->operands[0] = src;
       mem->operands[1] = addr;
       hsa_append_insn (hbb, mem);
     }
 
   /* HSAIL return instruction emission.  */
-  hsa_insn_basic *ret = hsa_alloc_basic_insn ();
-  ret->opcode = BRIG_OPCODE_RET;
+  hsa_insn_basic *ret = new hsa_insn_basic (0, BRIG_OPCODE_RET);
   hsa_append_insn (hbb, ret);
 }
 
@@ -1867,7 +1978,7 @@  gen_hsa_insns_for_known_library_call (gimple stmt, hsa_bb *hbb,
 	return true;
 
       hsa_op_reg *dest = hsa_reg_for_gimple_ssa (lhs, ssa_map);
-      hsa_op_immed *imm = hsa_alloc_immed_op (build_zero_cst (TREE_TYPE (lhs)));
+      hsa_op_immed *imm = new hsa_op_immed (build_zero_cst (TREE_TYPE (lhs)));
 
       hsa_build_append_simple_mov (dest, imm, hbb);
       return true;
@@ -1915,28 +2026,22 @@  specialop:
 	dest = hsa_reg_for_gimple_ssa (lhs, ssa_map);
 	/* We're using just one-dimensional kernels, so hard-coded
 	   dimension X.  */
-	hsa_op_immed *imm = hsa_alloc_immed_op (build_zero_cst
-						(uint32_type_node));
-	insn = hsa_alloc_basic_insn ();
+	hsa_op_immed *imm = new hsa_op_immed (build_zero_cst (uint32_type_node));
+	insn = new hsa_insn_basic (2, opcode);
 	if (dest->type != BRIG_TYPE_U32)
-	  {
-	    tmp = hsa_alloc_reg_op ();
-	    tmp->type = BRIG_TYPE_U32;
-	  }
+	  tmp = new hsa_op_reg (BRIG_TYPE_U32);
 	else
 	  tmp = dest;
-	insn->opcode = opcode;
 	insn->operands[0] = tmp;
 	insn->operands[1] = imm;
 	insn->type = tmp->type;
 	hsa_append_insn (hbb, insn);
 	if (dest != tmp)
 	  {
-	    insn = hsa_alloc_basic_insn ();
-	    insn->opcode = dest->type == BRIG_TYPE_S32 ? BRIG_OPCODE_MOV
+	    int opc2 = dest->type == BRIG_TYPE_S32 ? BRIG_OPCODE_MOV
 	      : BRIG_OPCODE_CVT;
+	    insn = new hsa_insn_basic (2, opc2, dest->type);
 	    insn->operands[0] = dest;
-	    insn->type = dest->type;
 	    insn->operands[1] = tmp;
 	    hsa_append_insn (hbb, insn);
 	  }
@@ -1950,13 +2055,10 @@  specialop:
 	 they cannot have side effects.  */
       if (!lhs)
 	return;
-      insn = hsa_alloc_basic_insn ();
-      insn->opcode = BRIG_OPCODE_SQRT;
       dest = hsa_reg_for_gimple_ssa (lhs, ssa_map);
+      insn = new hsa_insn_basic (2, BRIG_OPCODE_SQRT, dest->type);
       insn->operands[0] = dest;
       set_reg_def (dest, insn);
-      insn->type = dest->type;
-
       insn->operands[1]
 	= hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 0),
 					  hbb, ssa_map, insn);
@@ -1970,16 +2072,15 @@  specialop:
     case BUILT_IN_ATOMIC_LOAD_16:
       {
 	/* XXX Ignore mem model for now.  */
+	BrigType16_t mtype = mem_type_for_type (hsa_type_for_scalar_tree_type
+						(TREE_TYPE (lhs), false));
+	hsa_insn_mem *meminsn = new hsa_insn_mem (BRIG_OPCODE_LD, mtype);
 	hsa_op_address *addr;
-	hsa_insn_mem *meminsn = hsa_alloc_mem_insn ();
 	addr = gen_hsa_addr (gimple_call_arg (stmt, 0), hbb, ssa_map);
 	dest = hsa_reg_for_gimple_ssa (lhs, ssa_map);
 
-	meminsn->opcode = BRIG_OPCODE_LD;
 	/* Should check what the memory scope is */
 	meminsn->memoryscope = BRIG_MEMORY_SCOPE_WORKGROUP;
-	meminsn->type = mem_type_for_type (hsa_type_for_scalar_tree_type
-					   (TREE_TYPE (lhs), false));
 	meminsn->operands[0] = dest;
 	meminsn->operands[1] = addr;
 	meminsn->memoryorder = BRIG_MEMORY_ORDER_SC_ACQUIRE;
@@ -1998,16 +2099,16 @@  specialop:
     case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_16:
       {
 	/* XXX Ignore mem model for now.  */
+	BrigType16_t atype  = hsa_bittype_for_type
+	  (hsa_type_for_scalar_tree_type (TREE_TYPE (lhs), false));
+	hsa_insn_atomic *atominsn = new hsa_insn_atomic (BRIG_OPCODE_ATOMIC,
+							 BRIG_ATOMIC_CAS, atype);
 	hsa_op_address *addr;
-	hsa_insn_atomic *atominsn = hsa_alloc_atomic_insn ();
 	addr = gen_hsa_addr (gimple_call_arg (stmt, 0), hbb, ssa_map);
 	dest = hsa_reg_for_gimple_ssa (lhs, ssa_map);
 
-	atominsn->opcode = BRIG_OPCODE_ATOMIC;
 	/* Should check what the memory scope is */
 	atominsn->memoryscope = BRIG_MEMORY_SCOPE_WORKGROUP;
-	atominsn->type = hsa_bittype_for_type
-	  (hsa_type_for_scalar_tree_type (TREE_TYPE (lhs), false));
 	atominsn->operands[0] = dest;
 	atominsn->operands[1] = addr;
 	atominsn->operands[2]
@@ -2017,7 +2118,6 @@  specialop:
 	  = hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 2),
 					    hbb, ssa_map, atominsn);
 	atominsn->memoryorder = BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE;
-	atominsn->atomicop = BRIG_ATOMIC_CAS;
 
 	set_reg_def (dest, atominsn);
 	if (addr->reg)
@@ -2085,20 +2185,10 @@  gen_hsa_phi_from_gimple_phi (gimple gphi, hsa_bb *hbb,
   hsa_insn_phi *hphi;
   unsigned count = gimple_phi_num_args (gphi);
 
-  hphi = hsa_allocp_inst_phi->allocate ();
-  memset (hphi, 0, sizeof (hsa_insn_phi));
-  hphi->opcode = HSA_OPCODE_PHI;
+  hphi = new hsa_insn_phi (count);
   hphi->bb = hbb->bb;
   hphi->dest = hsa_reg_for_gimple_ssa (gimple_phi_result (gphi), ssa_map);
   set_reg_def (hphi->dest, hphi);
-  /* FIXME: Of course we will have to handle more predecessors, but just not
-     yet.  */
-  if (count > HSA_OPERANDS_PER_INSN)
-    {
-      sorry ("Support for HSA does not handle PHI nodes with more than "
-	     "%i operands", HSA_OPERANDS_PER_INSN);
-      return;
-    }
 
   for (unsigned i = 0; i < count; i++)
     {
@@ -2113,7 +2203,7 @@  gen_hsa_phi_from_gimple_phi (gimple gphi, hsa_bb *hbb,
 	{
 	  gcc_assert (is_gimple_min_invariant (op));
 	  if (!POINTER_TYPE_P (TREE_TYPE (op)))
-	    hphi->operands[i] = hsa_alloc_immed_op (op);
+	    hphi->operands[i] = new hsa_op_immed (op);
 	  else
 	    {
 	      sorry ("Support for HSA does not handle PHI nodes with constant "
@@ -2132,23 +2222,60 @@  gen_hsa_phi_from_gimple_phi (gimple gphi, hsa_bb *hbb,
     hbb->first_phi = hphi;
 }
 
+/* Constructor of class containing HSA-specific information about a basic
+   block.  CFG_BB is the CFG BB this HSA BB is associated with.  IDX is the new
+   index of this BB (so that the constructor does not attempt to use
+   hsa_cfun during its construction).  */
+
+hsa_bb::hsa_bb (basic_block cfg_bb, int idx)
+{
+  gcc_assert (!cfg_bb->aux);
+  cfg_bb->aux = this;
+  bb = cfg_bb;
+  first_insn = last_insn = NULL;
+  first_phi = last_phi = NULL;
+  index = idx;
+  livein = BITMAP_ALLOC (NULL);
+  liveout = BITMAP_ALLOC (NULL);
+}
+
+/* Constructor of class containing HSA-specific information about a basic
+   block.  CFG_BB is the CFG BB this HSA BB is associated with.  */
+
+hsa_bb::hsa_bb (basic_block cfg_bb)
+{
+  gcc_assert (!cfg_bb->aux);
+  cfg_bb->aux = this;
+  bb = cfg_bb;
+  first_insn = last_insn = NULL;
+  first_phi = last_phi = NULL;
+  index = hsa_cfun->hbb_count++;
+  livein = BITMAP_ALLOC (NULL);
+  liveout = BITMAP_ALLOC (NULL);
+}
+
+/* New operator of class with HSA information about a basic block.  */
+void *
+hsa_bb::operator new (size_t)
+{
+  return hsa_allocp_bb->allocate ();
+}
+
+/* Destructor of class representing HSA BB.  */
+
+hsa_bb::~hsa_bb ()
+{
+  BITMAP_FREE (livein);
+  BITMAP_FREE (liveout);
+}
+
 /* Create and initialize and return a new hsa_bb structure for a given CFG
    basic block BB.  */
 
 hsa_bb *
 hsa_init_new_bb (basic_block bb)
 {
-  hsa_bb *hbb = hsa_allocp_bb->allocate ();
-  memset (hbb, 0, sizeof (hsa_bb));
-
-  gcc_assert (!bb->aux);
-  bb->aux = hbb;
-  hbb->bb = bb;
-  hbb->index = hsa_cfun.hbb_count++;
-  hbb->label_ref.kind = BRIG_KIND_OPERAND_CODE_REF;
-  hbb->livein = BITMAP_ALLOC (NULL);
-  hbb->liveout = BITMAP_ALLOC (NULL);
-  return hbb;
+  return new hsa_bb (bb);
 }
 
 /* Go over gimple representation and generate our internal HSA one.  SSA_MAP
@@ -2199,55 +2326,51 @@  gen_function_parameters (vec <hsa_op_reg_p> ssa_map)
   tree parm;
   int i, count = 0;
 
-  ENTRY_BLOCK_PTR_FOR_FN (cfun)->aux = &hsa_cfun.prologue;
-  hsa_cfun.prologue.bb = ENTRY_BLOCK_PTR_FOR_FN (cfun);
-
   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);
+  hsa_cfun->input_args_count = count;
+  hsa_cfun->input_args = XCNEWVEC (hsa_symbol, 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, &hsa_cfun->input_args[i]);
+      hsa_cfun->input_args[i].segment = hsa_cfun->kern_p ? BRIG_SEGMENT_KERNARG :
 				       BRIG_SEGMENT_ARG;
 
-      hsa_cfun.input_args[i].linkage = BRIG_LINKAGE_FUNCTION;
+      hsa_cfun->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],
+      hsa_cfun->input_args[i].name = IDENTIFIER_POINTER (DECL_NAME (parm));
+      slot = hsa_cfun->local_symbols->find_slot (&hsa_cfun->input_args[i],
 						INSERT);
       gcc_assert (!*slot);
-      *slot = &hsa_cfun.input_args[i];
+      *slot = &hsa_cfun->input_args[i];
 
       if (is_gimple_reg (parm))
 	{
 	  tree ddef = ssa_default_def (cfun, parm);
 	  if (ddef && !has_zero_uses (ddef))
 	    {
-	      hsa_op_address *addr;
-	      hsa_insn_mem *mem = hsa_alloc_mem_insn ();
+	      BrigType16_t mtype = mem_type_for_type
+		(hsa_type_for_scalar_tree_type (TREE_TYPE (ddef), false));
+	      hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, mtype);
 	      hsa_op_reg *dest = hsa_reg_for_gimple_ssa (ddef, ssa_map);
+	      hsa_op_address *addr;
 
-	      addr = gen_hsa_addr (parm, &hsa_cfun.prologue, ssa_map);
-	      mem->opcode = BRIG_OPCODE_LD;
-	      mem->type = mem_type_for_type (hsa_type_for_scalar_tree_type
-					     (TREE_TYPE (ddef), false));
+	      addr = gen_hsa_addr (parm, &hsa_cfun->prologue, ssa_map);
 	      mem->operands[0] = dest;
 	      mem->operands[1] = addr;
 	      set_reg_def (dest, mem);
 	      gcc_assert (!addr->reg);
-	      hsa_append_insn (&hsa_cfun.prologue, mem);
+	      hsa_append_insn (&hsa_cfun->prologue, mem);
 	    }
 	}
     }
@@ -2256,14 +2379,14 @@  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);
+      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);
       gcc_assert (!*slot);
-      *slot = hsa_cfun.output_arg;
+      *slot = hsa_cfun->output_arg;
     }
 }
 
@@ -2278,15 +2401,15 @@  generate_hsa (bool kernel)
   vec <hsa_op_reg_p> ssa_map = vNULL;
 
   hsa_init_data_for_cfun ();
-  hsa_cfun.kern_p = kernel;
+  hsa_cfun->kern_p = kernel;
 
   ssa_map.safe_grow_cleared (SSANAMES (cfun)->length ());
-  hsa_cfun.name
+  hsa_cfun->name
     = xstrdup (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)));
-  hsa_sanitize_name (hsa_cfun.name);
+  hsa_sanitize_name (hsa_cfun->name);
 
-  if (hsa_cfun.kern_p)
-    hsa_add_kern_decl_mapping (current_function_decl, hsa_cfun.name);
+  if (hsa_cfun->kern_p)
+    hsa_add_kern_decl_mapping (current_function_decl, hsa_cfun->name);
 
   gen_function_parameters (ssa_map);
   if (seen_error ())
diff --git a/gcc/hsa-regalloc.c b/gcc/hsa-regalloc.c
index 0a8b77c..5e34f9c 100644
--- a/gcc/hsa-regalloc.c
+++ b/gcc/hsa-regalloc.c
@@ -55,7 +55,8 @@  along with GCC; see the file COPYING3.  If not see
 static void
 naive_process_phi (hsa_insn_phi *phi)
 {
-  for (int i = 0; i < HSA_OPERANDS_PER_INSN; i++)
+  unsigned count = phi->operands.length ();
+  for (unsigned i = 0; i < count; i++)
     {
       hsa_op_base *op = phi->operands[i];
       hsa_bb *hbb;
@@ -81,7 +82,7 @@  naive_outof_ssa (void)
 {
   basic_block bb;
 
-  hsa_cfun.in_ssa = false;
+  hsa_cfun->in_ssa = false;
 
   FOR_EACH_BB_FN (bb, cfun)
   {
@@ -200,8 +201,10 @@  rewrite_code_bb (basic_block bb, struct reg_class_desc *classes)
   for (insn = hbb->first_insn; insn; insn = next_insn)
     {
       next_insn = insn->next;
-      for (int i = 0; i < HSA_OPERANDS_PER_INSN && insn->operands[i]; i++)
+      unsigned count = insn->operands.length ();
+      for (unsigned i = 0; i < count; i++)
 	{
+	  gcc_checking_assert (insn->operands[i]);
 	  hsa_op_reg **regaddr = insn_reg_addr (insn, i);
 
 	  if (regaddr)
@@ -244,6 +247,7 @@  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:
@@ -348,9 +352,9 @@  dump_hsa_cfun_regalloc (FILE *f)
 {
   basic_block bb;
 
-  fprintf (f, "\nHSAIL IL for %s\n", hsa_cfun.name);
+  fprintf (f, "\nHSAIL IL for %s\n", hsa_cfun->name);
 
-  dump_hsa_bb (f, &hsa_cfun.prologue);
+  dump_hsa_bb (f, &hsa_cfun->prologue);
   FOR_EACH_BB_FN (bb, cfun)
   {
     hsa_bb *hbb = (struct hsa_bb *) bb->aux;
@@ -511,10 +515,12 @@  spill_at_interval (hsa_op_reg *reg, vec<hsa_op_reg*> *active)
 static void
 visit_insn (hsa_insn_basic *insn, vec<hsa_op_reg*> &ind2reg, int &insn_order)
 {
-  int opi;
+  unsigned opi;
+  unsigned count = insn->operands.length ();
   insn->number = insn_order++;
-  for (opi = 0; opi < HSA_OPERANDS_PER_INSN && insn->operands[opi]; opi++)
+  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;
@@ -526,16 +532,19 @@  visit_insn (hsa_insn_basic *insn, vec<hsa_op_reg*> &ind2reg, int &insn_order)
 static void
 remove_def_in_insn (bitmap &work, hsa_insn_basic *insn)
 {
-  int opi;
-  int ndefs = hsa_num_def_ops (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 < HSA_OPERANDS_PER_INSN && insn->operands[opi]; opi++)
+  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);
@@ -547,10 +556,12 @@  remove_def_in_insn (bitmap &work, hsa_insn_basic *insn)
 static void
 merge_live_range_for_insn (hsa_insn_basic *insn)
 {
-  int opi;
-  int ndefs = hsa_num_def_ops (insn);
-  for (opi = 0; opi < HSA_OPERANDS_PER_INSN && insn->operands[opi]; opi++)
+  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)
 	{
@@ -583,7 +594,7 @@  linear_scan_regalloc (struct reg_class_desc *classes)
      and the post order for liveness analysis, which is the same
      backward.  */
   n = pre_and_rev_post_order_compute (NULL, bbs, false);
-  ind2reg.safe_grow_cleared (hsa_cfun.reg_count);
+  ind2reg.safe_grow_cleared (hsa_cfun->reg_count);
 
   /* Give all instructions a linearized number, at the same time
      build a mapping from register index to register.  */
@@ -610,7 +621,7 @@  linear_scan_regalloc (struct reg_class_desc *classes)
     }
 
   /* Initialize all live ranges to [after-end, 0).  */
-  for (i = 0; i < hsa_cfun.reg_count; i++)
+  for (i = 0; i < hsa_cfun->reg_count; i++)
     if (ind2reg[i])
       ind2reg[i]->lr_begin = insn_order, ind2reg[i]->lr_end = 0;
 
@@ -713,18 +724,18 @@  linear_scan_regalloc (struct reg_class_desc *classes)
 
   /* All regs that have still their start at after all code actually
      are defined at the start of the routine (prologue).  */
-  for (i = 0; i < hsa_cfun.reg_count; i++)
+  for (i = 0; i < hsa_cfun->reg_count; i++)
     if (ind2reg[i] && ind2reg[i]->lr_begin == insn_order)
       ind2reg[i]->lr_begin = 0;
 
   /* Sort all intervals by increasing start point.  */
-  gcc_assert (ind2reg.length () == (size_t) hsa_cfun.reg_count);
+  gcc_assert (ind2reg.length () == (size_t) hsa_cfun->reg_count);
   ind2reg.qsort (cmp_begin);
   for (i = 0; i < 4; i++)
-    active[i].reserve_exact (hsa_cfun.reg_count);
+    active[i].reserve_exact (hsa_cfun->reg_count);
 
   /* Now comes the linear scan allocation.  */
-  for (i = 0; i < hsa_cfun.reg_count; i++)
+  for (i = 0; i < hsa_cfun->reg_count; i++)
     {
       hsa_op_reg *reg = ind2reg[i];
       if (!reg)
@@ -777,7 +788,7 @@  linear_scan_regalloc (struct reg_class_desc *classes)
       fprintf (dump_file, "------- After liveness: -------\n");
       dump_hsa_cfun_regalloc (dump_file);
       fprintf (dump_file, "  ----- Intervals:\n");
-      for (i = 0; i < hsa_cfun.reg_count; i++)
+      for (i = 0; i < hsa_cfun->reg_count; i++)
 	{
 	  hsa_op_reg *reg = ind2reg[i];
 	  if (!reg)
@@ -806,7 +817,7 @@  regalloc (void)
   reg_class_desc classes[4];
 
   /* If there are no registers used in the function, exit right away. */
-  if (hsa_cfun.reg_count == 0)
+  if (hsa_cfun->reg_count == 0)
     return;
 
   memset (classes, 0, sizeof (classes));
diff --git a/gcc/hsa.c b/gcc/hsa.c
index df41118..a9433b0 100644
--- a/gcc/hsa.c
+++ b/gcc/hsa.c
@@ -74,7 +74,7 @@  along with GCC; see the file COPYING3.  If not see
 
 /* Structure containing intermediate HSA representation of the generated
    function. */
-struct hsa_function_representation hsa_cfun;
+class hsa_function_representation *hsa_cfun;
 
 /* Element of the mapping vector between a host decl and an HSA kernel.  */
 
diff --git a/gcc/hsa.h b/gcc/hsa.h
index 1239d6c..1e9212b 100644
--- a/gcc/hsa.h
+++ b/gcc/hsa.h
@@ -28,7 +28,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "hash-table.h"
 #include "basic-block.h"
 
-struct hsa_insn_basic;
+class hsa_insn_basic;
 typedef hsa_insn_basic *hsa_insn_basic_p;
 
 /* Class representing an input argument, output argument (result) or a
@@ -67,8 +67,10 @@  struct hsa_symbol
 
 /* Abstract class for HSA instruction operands. */
 
-struct hsa_op_base
+class hsa_op_base
 {
+public:
+
   /* Next operand scheduled to be written when writing BRIG operand
      section.  */
   hsa_op_base *next;
@@ -79,22 +81,46 @@  struct hsa_op_base
 
   /* The type of a particular operand.  */
   BrigKind16_t kind;
+
+protected:
+  hsa_op_base (BrigKind16_t k);
+private:
+  /* Make the default constructor inaccessible.  */
+  hsa_op_base () {}
 };
 
 /* Common abstract ancestor for operands which have a type.  */
 
-struct hsa_op_with_type : public hsa_op_base
+class hsa_op_with_type : public hsa_op_base
 {
+public:
   /* The type.  */
   BrigType16_t type;
+
+protected:
+  hsa_op_with_type (BrigKind16_t k, BrigType16_t t);
+private:
+  /* Make the default constructor inaccessible.  */
+  hsa_op_with_type () : hsa_op_base (BRIG_KIND_NONE) {}
 };
 
 /* An immediate HSA operand.  */
 
-struct hsa_op_immed : public hsa_op_with_type
+class hsa_op_immed : public hsa_op_with_type
 {
+public:
+  hsa_op_immed (tree tree_val);
+  void *operator new (size_t);
+
   /* Value as represented by middle end.  */
   tree value;
+
+private:
+  /* Make the default constructor inaccessible.  */
+  hsa_op_immed () : hsa_op_with_type (BRIG_KIND_NONE, BRIG_TYPE_NONE) {}
+  /* All objects are deallocated by destroying their pool, so make delete
+     inaccessible too.  */
+  void operator delete (void *) {}
 };
 
 /* Report whether or not P is a an immediate operand.  */
@@ -109,12 +135,11 @@  is_a_helper <hsa_op_immed *>::test (hsa_op_base *p)
 
 /* HSA register operand.  */
 
-struct hsa_op_reg : public hsa_op_with_type
+class hsa_op_reg : public hsa_op_with_type
 {
-  /* Destructor.  */
-  ~hsa_op_reg ()
-  {
-  }
+public:
+  hsa_op_reg (BrigType16_t t);
+  void *operator new (size_t);
 
   /* Verify register operand.  */
   void verify ();
@@ -142,9 +167,16 @@  struct hsa_op_reg : public hsa_op_with_type
   /* If allocated, the number of the HW register (within its HSA register
      class). */
   char hard_num;
+
+private:
+  /* Make the default constructor inaccessible.  */
+  hsa_op_reg () : hsa_op_with_type (BRIG_KIND_NONE, BRIG_TYPE_NONE) {}
+  /* All objects are deallocated by destroying their pool, so make delete
+     inaccessible too.  */
+  void operator delete (void *) {}
 };
 
-typedef struct hsa_op_reg *hsa_op_reg_p;
+typedef class hsa_op_reg *hsa_op_reg_p;
 
 /* Report whether or not P is a register operand.  */
 
@@ -158,8 +190,12 @@  is_a_helper <hsa_op_reg *>::test (hsa_op_base *p)
 
 /* An address HSA operand.  */
 
-struct hsa_op_address : public hsa_op_base
+class hsa_op_address : public hsa_op_base
 {
+public:
+  hsa_op_address (hsa_symbol *sym, hsa_op_reg *reg, HOST_WIDE_INT offset);
+  void *operator new (size_t);
+
   /* Symbol base of the address.  Can be NULL if there is none.  */
   hsa_symbol *symbol;
 
@@ -168,6 +204,12 @@  struct hsa_op_address : public hsa_op_base
 
   /* Immediate byte offset.  */
   HOST_WIDE_INT imm_offset;
+private:
+  /* Make the default constructor inaccessible.  */
+  hsa_op_address () : hsa_op_base (BRIG_KIND_NONE) {}
+  /* All objects are deallocated by destroying their pool, so make delete
+     inaccessible too.  */
+  void operator delete (void *) {}
 };
 
 /* Report whether or not P is an address operand.  */
@@ -183,8 +225,11 @@  is_a_helper <hsa_op_address *>::test (hsa_op_base *p)
 /* A reference to code HSA operand. It can be either reference
    to a start of a BB or a start of a function.  */
 
-struct hsa_op_code_ref : public hsa_op_base
+class hsa_op_code_ref : public hsa_op_base
 {
+public:
+  hsa_op_code_ref ();
+
   /* Offset in the code section that this refers to.  */
   unsigned directive_offset;
 };
@@ -200,16 +245,22 @@  is_a_helper <hsa_op_code_ref *>::test (hsa_op_base *p)
 }
 
 /* Code list HSA operand.  */
-struct hsa_op_code_list: public hsa_op_base
+
+class hsa_op_code_list: public hsa_op_base
 {
-  /* Destructor.  */
-  ~hsa_op_code_list ()
-  {
-  }
+public:
+  hsa_op_code_list (unsigned elements);
+  void *operator new (size_t);
 
   /* Offset to variable-sized array in hsa_data section, where
      are offsets to entries in the hsa_code section.  */
   auto_vec<unsigned> offsets;
+private:
+  /* Make the default constructor inaccessible.  */
+  hsa_op_code_list () : hsa_op_base (BRIG_KIND_NONE) {}
+  /* All objects are deallocated by destroying their pool, so make delete
+     inaccessible too.  */
+  void operator delete (void *) {}
 };
 
 /* Report whether or not P is a code list operand.  */
@@ -222,16 +273,28 @@  is_a_helper <hsa_op_code_list *>::test (hsa_op_base *p)
   return p->kind == BRIG_KIND_OPERAND_CODE_LIST;
 }
 
-#define HSA_OPERANDS_PER_INSN 5
+/* Opcodes of instructions that are not part of HSA but that we use to
+   represent it nevertheless.  */
+
+#define HSA_OPCODE_PHI (-1)
+#define HSA_OPCODE_CALL_BLOCK (-2)
+
+/* The number of operand pointers we can directly in an instruction.  */
+#define HSA_BRIG_INT_STORAGE_OPERANDS 5
 
 /* Class representing an HSA instruction.  Unlike typical ancestors for
    specialized classes, this one is also directly used for all instructions
    that are then represented as BrigInstBasic.  */
 
-struct hsa_insn_basic
+class hsa_insn_basic
 {
+public:
+  hsa_insn_basic (unsigned nops, int opc);
+  hsa_insn_basic (unsigned nops, int opc, BrigType16_t t);
+  void *operator new (size_t);
+
   /* The previous and next instruction in the basic block.  */
-  struct hsa_insn_basic *prev, *next;
+  hsa_insn_basic *prev, *next;
 
   /* Basic block this instruction belongs to.  */
   basic_block bb;
@@ -241,28 +304,43 @@  struct hsa_insn_basic
      initially we use negative values for PHI nodes and such.  */
   int opcode;
 
-  int number;
+  int number;			/* FIXME: What is this for? */
 
   /* Type of the destination of the operations.  */
   BrigType16_t type;
 
-  /* The individual operands, NULL if unused.  */
-  struct hsa_op_base *operands[HSA_OPERANDS_PER_INSN];
+  /* The individual operands.  All instructions but PHI nodes have five or
+     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;
+  /* !!! */
+protected:
+  /* Make the default constructor inaccessible.  */
+  hsa_insn_basic () {}
+  /* All objects are deallocated by destroying their pool, so make delete
+     inaccessible too.  */
+  void operator delete (void *) {}
 };
 
-#define HSA_OPCODE_PHI -1
-#define HSA_OPCODE_CALL_BLOCK -2
-
-/* Structure representing a PHI node of the SSA form of HSA virtual
+/* Class representing a PHI node of the SSA form of HSA virtual
    registers.  */
 
-struct hsa_insn_phi : public hsa_insn_basic
+class hsa_insn_phi : public hsa_insn_basic
 {
-  /* Destination.  */
-  struct hsa_op_reg *dest;
+public:
+  hsa_insn_phi (unsigned nops);
+  void *operator new (size_t);
 
-  /* FIXME: In order to handle BBs with more than 5 predecessors we will need
-     more operands.  */
+  /* Destination.  */
+  hsa_op_reg *dest;
+
+private:
+  /* Make the default constructor inaccessible.  */
+  hsa_insn_phi () : hsa_insn_basic (1, HSA_OPCODE_PHI) {}
+  /* All objects are deallocated by destroying their pool, so make delete
+     inaccessible too.  */
+  void operator delete (void *) {}
 };
 
 /* Report whether or not P is a PHI node.  */
@@ -275,15 +353,23 @@  is_a_helper <hsa_insn_phi *>::test (hsa_insn_basic *p)
   return p->opcode == HSA_OPCODE_PHI;
 }
 
-/* HSA instruction for branches.  */
+/* HSA instruction for branches.  Currently we explicitely represent only
+   conditional branches.  */
 
-struct hsa_insn_br : public hsa_insn_basic
+class hsa_insn_br : public hsa_insn_basic
 {
-  /* FIXME: Modifiers are missing but I do not understand what ALU modifiers
-     can mean here.  */
+public:
+  hsa_insn_br (hsa_op_reg *ctrl);
+  void *operator new (size_t);
 
   /* Width as described in HSA documentation.  */
   BrigWidth8_t width;
+private:
+  /* Make the default constructor inaccessible.  */
+  hsa_insn_br () : hsa_insn_basic (1, BRIG_OPCODE_CBR) {}
+  /* All objects are deallocated by destroying their pool, so make delete
+     inaccessible too.  */
+  void operator delete (void *) {}
 };
 
 /* Report whether P is a branching instruction.  */
@@ -299,14 +385,25 @@  is_a_helper <hsa_insn_br *>::test (hsa_insn_basic *p)
 
 /* HSA instruction for comparisons.  */
 
-struct hsa_insn_cmp : public hsa_insn_basic
+class hsa_insn_cmp : public hsa_insn_basic
 {
+public:
+  hsa_insn_cmp (BrigCompareOperation8_t cmp, BrigType16_t t);
+  void *operator new (size_t);
+
   /* Source type should be derived from operand types.  */
 
   /* The comparison operation.  */
   BrigCompareOperation8_t compare;
 
-  /* TODO: Modifiers are missing but so are everywhere else.  */
+  /* TODO: Modifiers and packing control are missing but so are everywhere
+     else.  */
+private:
+  /* Make the default constructor inaccessible.  */
+  hsa_insn_cmp () : hsa_insn_basic (1, BRIG_OPCODE_CMP) {}
+  /* All objects are deallocated by destroying their pool, so make delete
+     inaccessible too.  */
+  void operator delete (void *) {}
 };
 
 /* Report whether or not P is a comparison instruction.  */
@@ -321,8 +418,12 @@  is_a_helper <hsa_insn_cmp *>::test (hsa_insn_basic *p)
 
 /* HSA instruction for memory operations.  */
 
-struct hsa_insn_mem : public hsa_insn_basic
+class hsa_insn_mem : public hsa_insn_basic
 {
+public:
+  hsa_insn_mem (int opc, BrigType16_t t);
+  void *operator new (size_t);
+
   /* The segment is of the memory access is either the segment of the symbol in
      the address operand or flat address is there is no symbol there.  */
 
@@ -336,6 +437,15 @@  struct hsa_insn_mem : public hsa_insn_basic
   enum BrigMemoryScope memoryscope;
 
   /* TODO:  Add width modifier, perhaps also other things.  */
+protected:
+  hsa_insn_mem (unsigned nops, int opc, BrigType16_t t);
+
+private:
+  /* Make the default constructor inaccessible.  */
+  hsa_insn_mem () : hsa_insn_basic (1, BRIG_OPCODE_LD) {}
+  /* All objects are deallocated by destroying their pool, so make delete
+     inaccessible too.  */
+  void operator delete (void *) {}
 };
 
 /* Report whether or not P is a memory instruction.  */
@@ -351,10 +461,20 @@  is_a_helper <hsa_insn_mem *>::test (hsa_insn_basic *p)
 
 /* HSA instruction for atomic operations.  */
 
-struct hsa_insn_atomic : public hsa_insn_mem
+class hsa_insn_atomic : public hsa_insn_mem
 {
+public:
+  hsa_insn_atomic (int opc, enum BrigAtomicOperation aop, BrigType16_t t);
+  void *operator new (size_t);
+
   /* The operation itself.  */
   enum BrigAtomicOperation atomicop;
+private:
+  /* Make the default constructor inaccessible.  */
+  hsa_insn_atomic () : hsa_insn_mem (1, BRIG_KIND_NONE, BRIG_TYPE_NONE) {}
+  /* All objects are deallocated by destroying their pool, so make delete
+     inaccessible too.  */
+  void operator delete (void *) {}
 };
 
 /* Report whether or not P is a memory instruction.  */
@@ -368,33 +488,25 @@  is_a_helper <hsa_insn_atomic *>::test (hsa_insn_basic *p)
 	  || p->opcode == BRIG_OPCODE_ATOMICNORET);
 }
 
-/* Though the HSA PRM in 19.10.1.7 says that LDA is should be BrigInstMem, the
-   verifier insists it is Brig Inst Addr, so provide it here too.  */
-
-struct hsa_insn_addr : public hsa_insn_basic
-{
-  /* The segment is of the memory access is either the segment of the symbol in
-     the address operand or flat address is there is no symbol there.  */
-};
-
-/* Report whether or not P is a memory address instruction.  */
-
-template <>
-template <>
-inline bool
-is_a_helper <hsa_insn_addr *>::test (hsa_insn_basic *p)
-{
-  return (p->opcode == BRIG_OPCODE_LDA);
-}
-
 /* HSA instruction to convert between flat addressing and segments.  */
 
-struct hsa_insn_seg : hsa_insn_basic
+class hsa_insn_seg : public hsa_insn_basic
 {
+public:
+  hsa_insn_seg (int opc, BrigType16_t destt, BrigType16_t srct,
+		BrigSegment8_t seg);
+  void *operator new (size_t);
+
   /* Source type.  Depends on the source addressing/segment.  */
   BrigType16_t src_type;
   /* The segment we are converting from or to.  */
   BrigSegment8_t segment;
+private:
+  /* Make the default constructor inaccessible.  */
+  hsa_insn_seg () : hsa_insn_basic (1, BRIG_OPCODE_STOF) {}
+  /* All objects are deallocated by destroying their pool, so make delete
+     inaccessible too.  */
+  void operator delete (void *) {}
 };
 
 /* Report whether or not P is a segment conversion instruction.  */
@@ -410,18 +522,17 @@  is_a_helper <hsa_insn_seg *>::test (hsa_insn_basic *p)
 
 /* HSA instruction for function call.  */
 
-struct hsa_insn_call: hsa_insn_basic
+class hsa_insn_call : public hsa_insn_basic
 {
-  /* Destructor.  */
-  ~hsa_insn_call ()
-  {
-  }
+public:
+  hsa_insn_call (tree callee);
+  void *operator new (size_t);
 
   /* Called function */
   tree called_function;
 
   /* Called function code reference.  */
-  struct hsa_op_code_ref func;
+  hsa_op_code_ref func;
 
   /* Argument symbols.  */
   auto_vec <hsa_symbol *> args_symbols;
@@ -434,6 +545,12 @@  struct hsa_insn_call: hsa_insn_basic
 
   /* Code list for result of the function.  */
   hsa_op_code_list *result_code_list;
+private:
+  /* Make the default constructor inaccessible.  */
+  hsa_insn_call () : hsa_insn_basic (0, BRIG_OPCODE_CALL) {}
+  /* All objects are deallocated by destroying their pool, so make delete
+     inaccessible too.  */
+  void operator delete (void *) {}
 };
 
 /* Report whether or not P is a call instruction.  */
@@ -452,12 +569,11 @@  is_a_helper <hsa_insn_call *>::test (hsa_insn_basic *p)
    Emission of the instruction will produce multiple
    HSAIL instructions.  */
 
-struct hsa_insn_call_block: hsa_insn_basic
+class hsa_insn_call_block : public hsa_insn_basic
 {
-  /* Destructor.  */
-  ~hsa_insn_call_block ()
-  {
-  }
+public:
+  hsa_insn_call_block ();
+  void *operator new (size_t);
 
   /* Input formal arguments.  */
   auto_vec <hsa_symbol *> input_args;
@@ -473,6 +589,10 @@  struct hsa_insn_call_block: hsa_insn_basic
 
   /* Call instruction.  */
   hsa_insn_call *call_insn;
+private:
+  /* All objects are deallocated by destroying their pool, so make delete
+     inaccessible too.  */
+  void operator delete (void *) {}
 };
 
 /* Report whether or not P is a call block instruction.  */
@@ -487,8 +607,14 @@  is_a_helper <hsa_insn_call_block *>::test (hsa_insn_basic *p)
 
 /* Basic block of HSA instructions.  */
 
-struct hsa_bb
+class hsa_bb
 {
+public:
+  hsa_bb (basic_block cfg_bb);
+  hsa_bb (basic_block cfg_bb, int idx);
+  ~hsa_bb ();
+  void *operator new (size_t);
+
   /* The real CFG BB that this HBB belongs to.  */
   basic_block bb;
 
@@ -496,14 +622,20 @@  struct hsa_bb
   hsa_op_code_ref label_ref;
 
   /* The first and last instruction.  */
-  struct hsa_insn_basic *first_insn, *last_insn;
+  hsa_insn_basic *first_insn, *last_insn;
   /* The first and last phi node.  */
-  struct hsa_insn_phi *first_phi, *last_phi;
+  hsa_insn_phi *first_phi, *last_phi;
 
   /* Just a number to construct names from.  */
   int index;
 
   bitmap liveout, livein;
+private:
+  /* Make the default constructor inaccessible.  */
+  hsa_bb ();
+  /* All objects are deallocated by destroying their pool, so make delete
+     inaccessible too.  */
+  void operator delete (void *) {}
 };
 
 /* Return the corresponding HSA basic block structure for the given control
@@ -570,8 +702,12 @@  hsa_free_symbol_hasher::equal (const value_type a, const compare_type b)
 /* Structure that encapsulates intermediate representation of a HSA
    function.  */
 
-struct hsa_function_representation
+class hsa_function_representation
 {
+public:
+  hsa_function_representation ();
+  ~hsa_function_representation ();
+
   /* Name of the function.  */
   char *name;
 
@@ -606,7 +742,7 @@  struct hsa_function_representation
 };
 
 /* in hsa.c */
-extern struct hsa_function_representation hsa_cfun;
+extern struct hsa_function_representation *hsa_cfun;
 extern hash_table <hsa_free_symbol_hasher> *hsa_global_variable_symbols;
 void hsa_init_compilation_unit_data (void);
 void hsa_deinit_compilation_unit_data (void);