@@ -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))
@@ -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;
@@ -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 ())
@@ -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));
@@ -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. */
@@ -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);