diff mbox

[hsa] Introduce alignment to hsa_insn_mem

Message ID 20151012174628.GE14248@virgil.suse.cz
State New
Headers show

Commit Message

Martin Jambor Oct. 12, 2015, 5:46 p.m. UTC
Hi,

the newest version of the finalizer actually honors alignment
information and therefore the compiler has to provide the correct
values, which is what the following patch does.

We may need to be more conservative in the cases when we expand memset
and memcpy inline, but I have committed this patch anyway, because
everywhere else it should be correct and the performance without it
was horrible.

Thanks,

Martin


2015-10-12  Martin Jambor  <mjambor@suse.cz>

	* hsa-brig.c (get_alignment): Removed.
	(emit_directive_variable): Use hsa_natural_alignment.
	(emit_memory_insn): Use alignment from mem.
	* hsa-gen.c (hsa_insn_mem::hsa_insn_mem): Initialize align.
	(gen_hsa_insns_for_bitfield_load): New argument, set alignment.
	(gen_hsa_insns_for_load): Set alignment.
	(gen_hsa_insns_for_store): Likewise.
	* hsa.c (hsa_alignment_encoding): New function.
	(hsa_natural_alignment): Likewise.
	(hsa_insn_mem::set_align): Likewise.
	* hsa.h (hsa_insn_mem): New members align and set_align.
	(hsa_alignment_encoding): Declare.
	(hsa_natural_alignment): Likewise.
---
 gcc/hsa-brig.c | 29 ++++-------------------------
 gcc/hsa-gen.c  | 23 +++++++++++++++++------
 gcc/hsa.c      | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
 gcc/hsa.h      |  9 +++++++++
 4 files changed, 79 insertions(+), 31 deletions(-)
diff mbox

Patch

diff --git a/gcc/hsa-brig.c b/gcc/hsa-brig.c
index b6eabfd..49d9e1d 100644
--- a/gcc/hsa-brig.c
+++ b/gcc/hsa-brig.c
@@ -477,29 +477,6 @@  brig_release_data (void)
   brig_initialized = 0;
 }
 
-/* Find the alignment base on the type.  */
-
-static BrigAlignment8_t
-get_alignment (BrigType16_t type)
-{
-  unsigned bit_size ;
-  bit_size = hsa_type_bit_size (type & ~BRIG_TYPE_ARRAY);
-
-  if (bit_size == 1)
-    return BRIG_ALIGNMENT_1;
-  if (bit_size == 8)
-    return BRIG_ALIGNMENT_1;
-  if (bit_size == 16)
-    return BRIG_ALIGNMENT_2;
-  if (bit_size == 32)
-    return BRIG_ALIGNMENT_4;
-  if (bit_size == 64)
-    return BRIG_ALIGNMENT_8;
-  if (bit_size == 128)
-    return BRIG_ALIGNMENT_16;
-  gcc_unreachable ();
-}
-
 /* Enqueue operation OP.  Return the offset at which it will be stored.  */
 
 static unsigned int
@@ -595,7 +572,9 @@  emit_directive_variable (struct hsa_symbol *symbol)
   dirvar.init = 0;
   dirvar.type = htole16 (symbol->type);
   dirvar.segment = symbol->segment;
-  dirvar.align = get_alignment (dirvar.type);
+  /* TODO: Once we are able to access global variables, we must copy their
+     alignment.  */
+  dirvar.align = MAX (hsa_natural_alignment (dirvar.type), BRIG_ALIGNMENT_4);
   dirvar.linkage = symbol->linkage;
   dirvar.dim.lo = (uint32_t) symbol->dim;
   dirvar.dim.hi = (uint32_t) ((unsigned long long) symbol->dim >> 32);
@@ -1161,7 +1140,7 @@  emit_memory_insn (hsa_insn_mem *mem)
     repr.segment = BRIG_SEGMENT_FLAT;
   repr.modifier.allBits = 0 ;
   repr.equivClass = mem->equiv_class;
-  repr.align = BRIG_ALIGNMENT_1;
+  repr.align = mem->align;
   if (mem->opcode == BRIG_OPCODE_LD)
     repr.width = BRIG_WIDTH_1;
   else
diff --git a/gcc/hsa-gen.c b/gcc/hsa-gen.c
index cf36882..d20efd8 100644
--- a/gcc/hsa-gen.c
+++ b/gcc/hsa-gen.c
@@ -76,6 +76,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "tree-cfg.h"
 #include "cfgloop.h"
 #include "cfganal.h"
+#include "builtins.h"
 
 /* Print a warning message and set that we have seen an error.  */
 
@@ -1324,6 +1325,7 @@  hsa_insn_mem::hsa_insn_mem (int opc, BrigType16_t t, hsa_op_base *arg0,
   gcc_checking_assert (opc == BRIG_OPCODE_LD || opc == BRIG_OPCODE_ST
 		       || opc == BRIG_OPCODE_EXPAND);
 
+  align = hsa_natural_alignment (t);
   equiv_class = 0;
 }
 
@@ -1337,6 +1339,7 @@  hsa_insn_mem::hsa_insn_mem (unsigned nops, int opc, BrigType16_t t,
 			    hsa_op_base *arg2, hsa_op_base *arg3)
   : hsa_insn_basic (nops, opc, t, arg0, arg1, arg2, arg3)
 {
+  align = hsa_natural_alignment (t);
   equiv_class = 0;
 }
 
@@ -2007,18 +2010,20 @@  gen_hsa_insns_for_bitfield (hsa_op_reg *dest, hsa_op_reg *value_reg,
 
 
 /* Generate HSAIL instructions loading a bit field into register DEST.  ADDR is
-   prepared memory address which is used to load the bit field.  To identify
-   a bit field BITPOS is offset to the loaded memory and BITSIZE is number
-   of bits of the bit field.  Add instructions to HBB.  */
+   prepared memory address which is used to load the bit field.  To identify a
+   bit field BITPOS is offset to the loaded memory and BITSIZE is number of
+   bits of the bit field.  Add instructions to HBB.  Load must be performaed in
+   alignment ALIGN.  */
 
 static void
 gen_hsa_insns_for_bitfield_load (hsa_op_reg *dest, hsa_op_address *addr,
-				HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
-				hsa_bb *hbb)
+				 HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
+				 hsa_bb *hbb, BrigAlignment8_t align)
 {
   hsa_op_reg *value_reg = new hsa_op_reg (dest->type);
   hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, dest->type, value_reg,
 					addr);
+  mem->set_align (align);
   hbb->append_insn (mem);
   gen_hsa_insns_for_bitfield (dest, value_reg, bitsize, bitpos, hbb);
 }
@@ -2140,8 +2145,11 @@  gen_hsa_insns_for_load (hsa_op_reg *dest, tree rhs, tree type, hsa_bb *hbb,
 	  return;
 	}
 
+      BrigAlignment8_t req_align;
+      req_align = hsa_alignment_encoding (get_object_alignment (rhs));
       if (bitsize || bitpos)
-	gen_hsa_insns_for_bitfield_load (dest, addr, bitsize, bitpos, hbb);
+	gen_hsa_insns_for_bitfield_load (dest, addr, bitsize, bitpos, hbb,
+					 req_align);
       else
 	{
 	  BrigType16_t mtype;
@@ -2150,6 +2158,7 @@  gen_hsa_insns_for_load (hsa_op_reg *dest, tree rhs, tree type, hsa_bb *hbb,
 								    false));
 	  hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, mtype, dest,
 						addr);
+	  mem->set_align (req_align);
 	  hbb->append_insn (mem);
 	}
     }
@@ -2221,6 +2230,7 @@  gen_hsa_insns_for_store (tree lhs, hsa_op_base *src, hsa_bb *hbb,
       /* Load value from memory.  */
       hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, mem_type,
 					    value_reg, addr);
+      mem->set_align (hsa_alignment_encoding (get_object_alignment (lhs)));
       hbb->append_insn (mem);
 
       /* AND the loaded value with prepared mask.  */
@@ -2263,6 +2273,7 @@  gen_hsa_insns_for_store (tree lhs, hsa_op_base *src, hsa_bb *hbb,
     }
 
   hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, mtype, src, addr);
+  mem->set_align (hsa_alignment_encoding (get_object_alignment (lhs)));
 
   /* XXX The HSAIL disasm has another constraint: if the source
      is an immediate then it must match the destination type.  If
diff --git a/gcc/hsa.c b/gcc/hsa.c
index 7da7b6c..1617ec6 100644
--- a/gcc/hsa.c
+++ b/gcc/hsa.c
@@ -327,6 +327,21 @@  hsa_insn_basic::num_used_ops ()
   return operand_count () - input_count ();
 }
 
+/* Set alignment to VALUE.  */
+
+void
+hsa_insn_mem::set_align (BrigAlignment8_t value)
+{
+  /* TODO: Perhaps remove this dump later on:  */
+  if (dump_file && (dump_flags & TDF_DETAILS)
+      && value < align)
+    {
+      fprintf (dump_file, "Decreasing alignment to %u in instruction ", value);
+      dump_hsa_insn (dump_file, this);
+    }
+  align = value;
+}
+
 /* Return size of HSA type T in bits.  */
 
 unsigned
@@ -455,6 +470,40 @@  hsa_type_integer_p (BrigType16_t type)
     }
 }
 
+/* Return HSA alignment encoding alignment to N bits.  */
+
+BrigAlignment8_t
+hsa_alignment_encoding (unsigned n)
+{
+  gcc_assert (n >= 8 && !(n & (n - 1)));
+  if (n >= 256)
+    return BRIG_ALIGNMENT_32;
+
+  switch (n)
+    {
+    case 8:
+      return BRIG_ALIGNMENT_1;
+    case 16:
+      return BRIG_ALIGNMENT_2;
+    case 32:
+      return BRIG_ALIGNMENT_4;
+    case 64:
+      return BRIG_ALIGNMENT_8;
+    case 128:
+      return BRIG_ALIGNMENT_16;
+    default:
+      gcc_unreachable ();
+    }
+}
+
+/* Return natural alignment of HSA TYPE.  */
+
+BrigAlignment8_t
+hsa_natural_alignment (BrigType16_t type)
+{
+  return hsa_alignment_encoding (hsa_type_bit_size (type & ~BRIG_TYPE_ARRAY));
+}
+
 /* Call the correct destructor on a statement STMT.  */
 
 void
diff --git a/gcc/hsa.h b/gcc/hsa.h
index 3c49d1b..d966454 100644
--- a/gcc/hsa.h
+++ b/gcc/hsa.h
@@ -541,9 +541,16 @@  public:
 
   void *operator new (size_t);
 
+  /* Set alignment to VALUE.  */
+
+  void set_align (BrigAlignment8_t value);
+
   /* 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.  */
 
+  /* Required alignment of the memory operation. */
+  BrigAlignment8_t align;
+
   /* HSA equiv class, basically an alias set number. */
   uint8_t equiv_class;
 
@@ -1056,6 +1063,8 @@  unsigned hsa_type_bit_size (BrigType16_t t);
 BrigType16_t hsa_bittype_for_type (BrigType16_t t);
 bool hsa_type_float_p (BrigType16_t type);
 bool hsa_type_integer_p (BrigType16_t type);
+BrigAlignment8_t hsa_alignment_encoding (unsigned n);
+BrigAlignment8_t hsa_natural_alignment (BrigType16_t type);
 void hsa_destroy_insn (hsa_insn_basic *insn);
 void hsa_add_kern_decl_mapping (tree decl, char *name, unsigned);
 unsigned hsa_get_number_decl_kernel_mappings (void);