@@ -1496,11 +1496,29 @@ emit_cmp_insn (hsa_insn_cmp *cmp)
brig_insn_count++;
}
-/* Emit an HSA branching instruction and all necessary directives, schedule
- necessary operands for writing. */
+/* Emit an HSA generic branching/sycnronization instruction. */
+
+static void
+emit_generic_branch_insn (hsa_insn_br *br)
+{
+ struct BrigInstBr repr;
+ repr.base.base.byteCount = lendian16 (sizeof (repr));
+ repr.base.base.kind = lendian16 (BRIG_KIND_INST_BR);
+ repr.base.opcode = lendian16 (br->m_opcode);
+ repr.width = br->m_width;
+ repr.base.type = lendian16 (br->m_type);
+ repr.base.operands = lendian32 (emit_insn_operands (br));
+ memset (&repr.reserved, 0, sizeof (repr.reserved));
+
+ brig_code.add (&repr, sizeof (repr));
+ brig_insn_count++;
+}
+
+/* Emit an HSA conditional branching instruction and all necessary directives,
+ schedule necessary operands for writing. */
static void
-emit_branch_insn (hsa_insn_br *br)
+emit_cond_branch_insn (hsa_insn_cbr *br)
{
struct BrigInstBr repr;
@@ -1513,7 +1531,7 @@ emit_branch_insn (hsa_insn_br *br)
repr.base.base.byteCount = lendian16 (sizeof (repr));
repr.base.base.kind = lendian16 (BRIG_KIND_INST_BR);
repr.base.opcode = lendian16 (br->m_opcode);
- repr.width = BRIG_WIDTH_1;
+ repr.width = br->m_width;
/* For Conditional jumps the type is always B1. */
repr.base.type = lendian16 (BRIG_TYPE_B1);
@@ -1885,8 +1903,8 @@ emit_insn (hsa_insn_basic *insn)
emit_segment_insn (seg);
else if (hsa_insn_cmp *cmp = dyn_cast <hsa_insn_cmp *> (insn))
emit_cmp_insn (cmp);
- else if (hsa_insn_br *br = dyn_cast <hsa_insn_br *> (insn))
- emit_branch_insn (br);
+ else if (hsa_insn_cbr *br = dyn_cast <hsa_insn_cbr *> (insn))
+ emit_cond_branch_insn (br);
else if (hsa_insn_sbr *sbr = dyn_cast <hsa_insn_sbr *> (insn))
{
if (switch_instructions == NULL)
@@ -1895,6 +1913,8 @@ emit_insn (hsa_insn_basic *insn)
switch_instructions->safe_push (sbr);
emit_switch_insn (sbr);
}
+ else if (hsa_insn_br *br = dyn_cast <hsa_insn_br *> (insn))
+ emit_generic_branch_insn (br);
else if (hsa_insn_arg_block *block = dyn_cast <hsa_insn_arg_block *> (insn))
emit_arg_block_insn (block);
else if (hsa_insn_call *call = dyn_cast <hsa_insn_call *> (insn))
@@ -621,6 +621,88 @@ hsa_m_atomicop_name (enum BrigAtomicOperation op)
}
}
+/* Return textual name for atomic operation. */
+
+static const char *
+hsa_width_specifier_name (BrigWidth8_t width)
+{
+ switch (width)
+ {
+ case BRIG_WIDTH_NONE:
+ return "none";
+ case BRIG_WIDTH_1:
+ return "1";
+ case BRIG_WIDTH_2:
+ return "2";
+ case BRIG_WIDTH_4:
+ return "4";
+ case BRIG_WIDTH_8:
+ return "8";
+ case BRIG_WIDTH_16:
+ return "16";
+ case BRIG_WIDTH_32:
+ return "32";
+ case BRIG_WIDTH_64:
+ return "64";
+ case BRIG_WIDTH_128:
+ return "128";
+ case BRIG_WIDTH_256:
+ return "256";
+ case BRIG_WIDTH_512:
+ return "512";
+ case BRIG_WIDTH_1024:
+ return "1024";
+ case BRIG_WIDTH_2048:
+ return "2048";
+ case BRIG_WIDTH_4096:
+ return "4096";
+ case BRIG_WIDTH_8192:
+ return "8192";
+ case BRIG_WIDTH_16384:
+ return "16384";
+ case BRIG_WIDTH_32768:
+ return "32768";
+ case BRIG_WIDTH_65536:
+ return "65536";
+ case BRIG_WIDTH_131072:
+ return "131072";
+ case BRIG_WIDTH_262144:
+ return "262144";
+ case BRIG_WIDTH_524288:
+ return "524288";
+ case BRIG_WIDTH_1048576:
+ return "1048576";
+ case BRIG_WIDTH_2097152:
+ return "2097152";
+ case BRIG_WIDTH_4194304:
+ return "4194304";
+ case BRIG_WIDTH_8388608:
+ return "8388608";
+ case BRIG_WIDTH_16777216:
+ return "16777216";
+ case BRIG_WIDTH_33554432:
+ return "33554432";
+ case BRIG_WIDTH_67108864:
+ return "67108864";
+ case BRIG_WIDTH_134217728:
+ return "134217728";
+ case BRIG_WIDTH_268435456:
+ return "268435456";
+ case BRIG_WIDTH_536870912:
+ return "536870912";
+ case BRIG_WIDTH_1073741824:
+ return "1073741824";
+ case BRIG_WIDTH_2147483648:
+ return "2147483648";
+ case BRIG_WIDTH_WAVESIZE:
+ return "wavesize";
+ case BRIG_WIDTH_ALL:
+ return "all";
+ default:
+ return "UNKNOWN_WIDTH";
+ }
+}
+
/* Dump textual representation of HSA IL register REG to file F. */
static void
@@ -884,9 +966,9 @@ dump_hsa_insn_1 (FILE *f, hsa_insn_basic *insn, int *indent)
fprintf (f, ", ");
dump_hsa_operand (f, cmp->get_op (2));
}
- else if (is_a <hsa_insn_br *> (insn))
+ else if (is_a <hsa_insn_cbr *> (insn))
{
- hsa_insn_br *br = as_a <hsa_insn_br *> (insn);
+ hsa_insn_cbr *br = as_a <hsa_insn_cbr *> (insn);
basic_block target = NULL;
edge_iterator ei;
edge e;
@@ -921,6 +1003,12 @@ dump_hsa_insn_1 (FILE *f, hsa_insn_basic *insn, int *indent)
fprintf (f, ", ");
}
}
+ else if (is_a <hsa_insn_br *> (insn))
+ {
+ hsa_insn_br *br = as_a <hsa_insn_br *> (insn);
+ fprintf (f, "%s_width(%s) ", hsa_opcode_name (br->m_opcode),
+ hsa_width_specifier_name (br->m_width));
+ }
else if (is_a <hsa_insn_arg_block *> (insn))
{
hsa_insn_arg_block *arg_block = as_a <hsa_insn_arg_block *> (insn);
@@ -1420,20 +1420,39 @@ hsa_insn_phi::operator new (size_t size)
return obstack_alloc (&hsa_obstack, size);
}
+/* Constructor of class representing instructions for control flow and
+ sychronization, */
+
+hsa_insn_br::hsa_insn_br (unsigned nops, int opc, BrigType16_t t,
+ BrigWidth8_t width, hsa_op_base *arg0,
+ hsa_op_base *arg1, hsa_op_base *arg2,
+ hsa_op_base *arg3)
+ : hsa_insn_basic (nops, opc, t, arg0, arg1, arg2, arg3),
+ m_width (width)
+{
+}
+
+/* New operator to allocate branch instruction from obstack. */
+
+void *
+hsa_insn_br::operator new (size_t size)
+{
+ return obstack_alloc (&hsa_obstack, size);
+}
+
/* Constructor of class representing instruction for conditional jump, CTRL is
the control register determining whether the jump will be carried out, the
new instruction is automatically added to its uses list. */
-hsa_insn_br::hsa_insn_br (hsa_op_reg *ctrl)
- : hsa_insn_basic (1, BRIG_OPCODE_CBR, BRIG_TYPE_B1, ctrl),
- m_width (BRIG_WIDTH_1)
+hsa_insn_cbr::hsa_insn_cbr (hsa_op_reg *ctrl)
+ : hsa_insn_br (1, BRIG_OPCODE_CBR, BRIG_TYPE_B1, BRIG_WIDTH_1, ctrl)
{
}
/* New operator to allocate branch instruction from obstack. */
void *
-hsa_insn_br::operator new (size_t size)
+hsa_insn_cbr::operator new (size_t size)
{
return obstack_alloc (&hsa_obstack, size);
}
@@ -3323,14 +3342,14 @@ static void
gen_hsa_insns_for_cond_stmt (gimple *cond, hsa_bb *hbb)
{
hsa_op_reg *ctrl = new hsa_op_reg (BRIG_TYPE_B1);
- hsa_insn_br *cbr;
+ hsa_insn_cbr *cbr;
gen_hsa_cmp_insn_from_gimple (gimple_cond_code (cond),
gimple_cond_lhs (cond),
gimple_cond_rhs (cond),
ctrl, hbb);
- cbr = new hsa_insn_br (ctrl);
+ cbr = new hsa_insn_cbr (ctrl);
hbb->append_insn (cbr);
}
@@ -3407,7 +3426,7 @@ gen_hsa_insns_for_switch_stmt (gswitch *s, hsa_bb *hbb)
hbb->append_insn (new hsa_insn_basic (3, BRIG_OPCODE_AND, cmp_reg->m_type,
cmp_reg, cmp1_reg, cmp2_reg));
- hbb->append_insn (new hsa_insn_br (cmp_reg));
+ hbb->append_insn (new hsa_insn_cbr (cmp_reg));
tree default_label = gimple_switch_default_label (s);
basic_block default_label_bb = label_to_block_fn (func,
@@ -4824,7 +4843,7 @@ gen_hsa_insns_for_kernel_call (hsa_bb *hbb, gcall *call)
signal_result_reg, imm);
new_hbb->append_insn (cmp);
- new_hbb->append_insn (new hsa_insn_br (ctrl));
+ new_hbb->append_insn (new hsa_insn_cbr (ctrl));
if (TREE_CODE (argument) == ADDR_EXPR)
{
@@ -4983,7 +5002,7 @@ expand_string_operation_builtin (gimple *stmt, hsa_bb *hbb,
{
edge e = split_block (hbb->m_bb, stmt);
basic_block condition_bb = e->src;
- hbb->append_insn (new hsa_insn_br (misaligned_flag));
+ hbb->append_insn (new hsa_insn_cbr (misaligned_flag));
/* Prepare the control flow. */
edge condition_edge = EDGE_SUCC (condition_bb, 0);
@@ -605,8 +605,8 @@ hsa_destroy_insn (hsa_insn_basic *insn)
{
if (hsa_insn_phi *phi = dyn_cast <hsa_insn_phi *> (insn))
phi->~hsa_insn_phi ();
- else if (hsa_insn_br *br = dyn_cast <hsa_insn_br *> (insn))
- br->~hsa_insn_br ();
+ else if (hsa_insn_cbr *br = dyn_cast <hsa_insn_cbr *> (insn))
+ br->~hsa_insn_cbr ();
else if (hsa_insn_cmp *cmp = dyn_cast <hsa_insn_cmp *> (insn))
cmp->~hsa_insn_cmp ();
else if (hsa_insn_mem *mem = dyn_cast <hsa_insn_mem *> (insn))
@@ -621,6 +621,8 @@ hsa_destroy_insn (hsa_insn_basic *insn)
block->~hsa_insn_arg_block ();
else if (hsa_insn_sbr *sbr = dyn_cast <hsa_insn_sbr *> (insn))
sbr->~hsa_insn_sbr ();
+ else if (hsa_insn_br *br = dyn_cast <hsa_insn_br *> (insn))
+ br->~hsa_insn_br ();
else if (hsa_insn_comment *comment = dyn_cast <hsa_insn_comment *> (insn))
comment->~hsa_insn_comment ();
else
@@ -513,35 +513,66 @@ is_a_helper <hsa_insn_phi *>::test (hsa_insn_basic *p)
return p->m_opcode == HSA_OPCODE_PHI;
}
-/* HSA instruction for branches. Currently we explicitely represent only
- conditional branches. */
-
+/* HSA instruction for */
class hsa_insn_br : public hsa_insn_basic
{
public:
- hsa_insn_br (hsa_op_reg *ctrl);
+ hsa_insn_br (unsigned nops, int opc, BrigType16_t t, BrigWidth8_t width,
+ hsa_op_base *arg0 = NULL, hsa_op_base *arg1 = NULL,
+ hsa_op_base *arg2 = NULL, hsa_op_base *arg3 = NULL);
void *operator new (size_t);
- /* Width as described in HSA documentation. */
+ /* Number of work-items affected in the same way by the instruction. */
BrigWidth8_t m_width;
+
private:
/* Make the default constructor inaccessible. */
- hsa_insn_br () : hsa_insn_basic (1, BRIG_OPCODE_CBR) {}
+ hsa_insn_br () : hsa_insn_basic (0, BRIG_OPCODE_BR) {}
/* All objects are deallocated by destroying their pool, so make delete
inaccessible too. */
void operator delete (void *) {}
};
-/* Report whether P is a branching instruction. */
+/* Return true if P is a branching/synchronization instruction. */
template <>
template <>
inline bool
is_a_helper <hsa_insn_br *>::test (hsa_insn_basic *p)
{
- return p->m_opcode == BRIG_OPCODE_BR
- || p->m_opcode == BRIG_OPCODE_CBR;
+ return p->m_opcode == BRIG_OPCODE_BARRIER
+ || p->m_opcode == BRIG_OPCODE_BR;
+}
+
+/* HSA instruction for conditional branches. Structurally the same as
+ hsa_insn_br but we represent it specially because of inherent control
+ flow it represents. */
+
+class hsa_insn_cbr : public hsa_insn_br
+{
+public:
+ hsa_insn_cbr (hsa_op_reg *ctrl);
+
+ void *operator new (size_t);
+
+private:
+ /* Make the default constructor inaccessible. */
+ hsa_insn_cbr () : hsa_insn_br (0, BRIG_OPCODE_CBR, BRIG_TYPE_B1,
+ BRIG_WIDTH_1) {}
+ /* All objects are deallocated by destroying their pool, so make delete
+ inaccessible too. */
+ void operator delete (void *) {}
+};
+
+/* Report whether P is a contitional branching instruction. */
+
+template <>
+template <>
+inline bool
+is_a_helper <hsa_insn_cbr *>::test (hsa_insn_basic *p)
+{
+ return p->m_opcode == BRIG_OPCODE_CBR;
}
/* HSA instruction for switch branches. */