diff mbox

[hsa] Represent atomic loads with atomic insn, introduce set_op

Message ID 20150903144305.GP2685@virgil.suse.cz
State New
Headers show

Commit Message

Martin Jambor Sept. 3, 2015, 2:43 p.m. UTC
Hi,

generation of atomic load instructions was still in its first ancient
implementation when it was not generating atomic loads at all.  This
is fixed by the subsequent patch.

The patch also introduces a method of hsa_insn_basic set_op which we
plan to use to use almost everywhere to set instruction operands.  It
has the advantage of automatically keeping SSA form of
pseudoregisters.

Committed to the branch after rudimantary HSA testing.

Thanks,

Martin


2015-09-03  Martin Jambor  <mjambor@suse.cz>

	* hsa.h (hsa_insn_mem): Move fields memoryorder and
	memoryscope...
	(hsa_insn_atomic): ...here.  Also add new operator.
	* hsa-dump.c (dump_hsa_insn): Do not dump removed fields.
	* hsa-gen.c (hsa_insn_mem): Remove initialization of removed
	fields.
	(hsa_insn_mem): Likewise.
	(hsa_insn_atomic::hsa_insn_atomic): Initialize new fields.
	(hsa_insn_atomic::new): New.
	(gen_hsa_insns_for_call): Create atomic instruction for atomic
	loads.
---
 gcc/ChangeLog.hsa | 20 +++++++++++++++++
 gcc/hsa-dump.c    |  4 ----
 gcc/hsa-gen.c     | 64 ++++++++++++++++++++++++++++++++++++++++---------------
 gcc/hsa.h         | 15 +++++++------
 4 files changed, 76 insertions(+), 27 deletions(-)
diff mbox

Patch

diff --git a/gcc/hsa-dump.c b/gcc/hsa-dump.c
index 4d78519..af61ebc 100644
--- a/gcc/hsa-dump.c
+++ b/gcc/hsa-dump.c
@@ -796,10 +796,6 @@  dump_hsa_insn (FILE *f, hsa_insn_basic *insn, int *indent)
       fprintf (f, "%s", hsa_opcode_name (mem->opcode));
       if (addr->symbol)
 	fprintf (f, "_%s", hsa_seg_name (addr->symbol->segment));
-      if (mem->memoryorder != BRIG_MEMORY_ORDER_NONE)
-	fprintf (f, "_%s", hsa_memsem_name (mem->memoryorder));
-      if (mem->memoryscope != BRIG_MEMORY_SCOPE_NONE)
-	fprintf (f, "_%s", hsa_memscope_name (mem->memoryscope));
       if (mem->equiv_class != 0)
 	fprintf (f, "_equiv(%i)", mem->equiv_class);
       fprintf (f, "_%s ", hsa_type_name (mem->type));
diff --git a/gcc/hsa-gen.c b/gcc/hsa-gen.c
index 92df7e4..cbfc75a 100644
--- a/gcc/hsa-gen.c
+++ b/gcc/hsa-gen.c
@@ -888,6 +888,31 @@  hsa_insn_basic::hsa_insn_basic (unsigned nops, int opc)
     operands.safe_grow_cleared (nops);
 }
 
+/* Make OP the operand number INDEX of operands of this instuction.  If OP is a
+   register or an address containing a register, then either set the definition
+   of the register to this instruction if it an output operand or add this
+   instruction to the uses if it is an input one.  */
+
+void
+hsa_insn_basic::set_op (int index, hsa_op_base *op)
+{
+  if (hsa_opcode_op_output_p (opcode, index))
+    {
+      if (hsa_op_reg *reg = dyn_cast <hsa_op_reg *> (op))
+	reg->set_definition (this);
+    }
+    else
+      {
+	hsa_op_address *addr;
+	if (hsa_op_reg *reg = dyn_cast <hsa_op_reg *> (op))
+	  reg->uses.safe_push (this);
+	else if ((addr = dyn_cast <hsa_op_address *> (op))
+		 && addr->reg)
+	  addr->reg->uses.safe_push (this);
+      }
+  operands[index] = op;
+}
+
 /* 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
@@ -1005,8 +1030,6 @@  hsa_insn_mem::hsa_insn_mem (int opc, BrigType16_t t, hsa_op_base *arg0,
 		       || opc == BRIG_OPCODE_EXPAND);
 
   equiv_class = 0;
-  memoryorder = BRIG_MEMORY_ORDER_NONE;
-  memoryscope = BRIG_MEMORY_SCOPE_NONE;
   operands[0] = arg0;
   operands[1] = arg1;
 }
@@ -1019,8 +1042,6 @@  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;
 }
 
 /* New operator to allocate memory instruction from pool alloc.  */
@@ -1031,9 +1052,9 @@  hsa_insn_mem::operator new (size_t)
   return hsa_allocp_inst_mem->vallocate ();
 }
 
-/* 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.  */
+/* Constructor of class representing atomic instructions and signals. OPC is
+   the prinicpal opcode, aop is the specific atomic operation opcode.  T is the
+   type of the instruction.  */
 
 hsa_insn_atomic::hsa_insn_atomic (int nops, int opc,
 				  enum BrigAtomicOperation aop,
@@ -1045,6 +1066,18 @@  hsa_insn_atomic::hsa_insn_atomic (int nops, int opc,
 		       opc == BRIG_OPCODE_SIGNAL ||
 		       opc == BRIG_OPCODE_SIGNALNORET);
   atomicop = aop;
+  /* TODO: Review the following defaults (together with the few overriddes we
+     have in the code).  */
+  memoryorder = BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE;
+  memoryscope = BRIG_MEMORY_SCOPE_SYSTEM;
+}
+
+/* New operator to allocate signal instruction from pool alloc.  */
+
+void *
+hsa_insn_atomic::operator new (size_t)
+{
+  return hsa_allocp_inst_atomic->vallocate ();
 }
 
 /* Constructor of class representing signal instructions.  OPC is the prinicpa;
@@ -3399,6 +3432,7 @@  specialop:
       /* FIXME: Using the native instruction may not be precise enough.
 	 Perhaps only allow if using -ffast-math?  */
       gen_hsa_unaryop_for_builtin (BRIG_OPCODE_NSIN, stmt, hbb, ssa_map);
+      break;
 
     case BUILT_IN_ATOMIC_LOAD_1:
     case BUILT_IN_ATOMIC_LOAD_2:
@@ -3412,17 +3446,13 @@  specialop:
 	hsa_op_address *addr = gen_hsa_addr (gimple_call_arg (stmt, 0),
 					     hbb, ssa_map);
 	dest = hsa_reg_for_gimple_ssa (lhs, ssa_map);
-	hsa_insn_mem *meminsn = new hsa_insn_mem (BRIG_OPCODE_LD, mtype, dest,
-						  addr);
-
-	/* Should check what the memory scope is */
-	meminsn->memoryscope = BRIG_MEMORY_SCOPE_WORKGROUP;
-	meminsn->memoryorder = BRIG_MEMORY_ORDER_SC_ACQUIRE;
+	hsa_insn_atomic *atominsn
+	  = new hsa_insn_atomic (2, BRIG_OPCODE_ATOMIC, BRIG_ATOMIC_LD, mtype);
 
-	dest->set_definition (meminsn);
-	if (addr->reg)
-	  addr->reg->uses.safe_push (meminsn);
-	hbb->append_insn (meminsn);
+	atominsn->set_op (0, dest);
+	atominsn->set_op (1, addr);
+	atominsn->memoryorder = BRIG_MEMORY_ORDER_SC_ACQUIRE;
+	hbb->append_insn (atominsn);
 	break;
       }
 
diff --git a/gcc/hsa.h b/gcc/hsa.h
index 8ebfcaa..9f8ce66 100644
--- a/gcc/hsa.h
+++ b/gcc/hsa.h
@@ -333,6 +333,7 @@  public:
 		  hsa_op_base *arg3 = NULL);
 
   void *operator new (size_t);
+  void set_op (int index, hsa_op_base *op);
 
   /* The previous and next instruction in the basic block.  */
   hsa_insn_basic *prev, *next;
@@ -474,12 +475,6 @@  public:
   /* HSA equiv class, basically an alias set number. */
   uint8_t equiv_class;
 
-  /* Things like acquire/release/aligned.  */
-  enum BrigMemoryOrder memoryorder;
-
-  /* Scope of the atomic operation. */
-  enum BrigMemoryScope memoryscope;
-
   /* TODO:  Add width modifier, perhaps also other things.  */
 protected:
   hsa_insn_mem (unsigned nops, int opc, BrigType16_t t);
@@ -510,9 +505,17 @@  class hsa_insn_atomic : public hsa_insn_mem
 public:
   hsa_insn_atomic (int nops, int opc, enum BrigAtomicOperation aop,
 		   BrigType16_t t);
+  void *operator new (size_t);
 
   /* The operation itself.  */
   enum BrigAtomicOperation atomicop;
+
+  /* Things like acquire/release/aligned.  */
+  enum BrigMemoryOrder memoryorder;
+
+  /* Scope of the atomic operation. */
+  enum BrigMemoryScope memoryscope;
+
 private:
   /* Make the default constructor inaccessible.  */
   hsa_insn_atomic () : hsa_insn_mem (1, BRIG_KIND_NONE, BRIG_TYPE_NONE) {}