@@ -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
@@ -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
@@ -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
@@ -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);