[hsa] Rename hsa.[ch] to hsa-common.[ch]
authorMartin Jambor <mjambor@suse.cz>
Fri, 20 Jan 2017 13:33:29 +0000 (14:33 +0100)
committerMartin Jambor <jamborm@gcc.gnu.org>
Fri, 20 Jan 2017 13:33:29 +0000 (14:33 +0100)
2017-01-20  Martin Jambor  <mjambor@suse.cz>

        * hsa.h: Renaed to hsa-common.h.  Adjusted a comment.
        * hsa.c: Renaed to hsa-common.c.  Change include of gt-hsa.h to
        gt-hsa-common.h.
        * Makefile.in (OBJS): Rename hsa.o to hsa-common.o.
        (GTFILES): Rename hsa.c to hsa-common.c.
        * hsa-brig.c: Change include of hsa.h to hsa-common.h.
        * hsa-dump.c: Likewise.
        * hsa-gen.c: Likewise.
        * hsa-regalloc.c: Likewise.
        * ipa-hsa.c: Likewise.
        * omp-expand.c: Likewise.
        * omp-low.c: Likewise.
        * toplev.c: Likewise.

From-SVN: r244711

14 files changed:
gcc/ChangeLog
gcc/Makefile.in
gcc/hsa-brig.c
gcc/hsa-common.c [new file with mode: 0644]
gcc/hsa-common.h [new file with mode: 0644]
gcc/hsa-dump.c
gcc/hsa-gen.c
gcc/hsa-regalloc.c
gcc/hsa.c [deleted file]
gcc/hsa.h [deleted file]
gcc/ipa-hsa.c
gcc/omp-expand.c
gcc/omp-low.c
gcc/toplev.c

index 38eeb5a21b9af9ca23b2609a044f54c72b38bbee..a27331249b8ef017eccb37d6066bb94162923293 100644 (file)
@@ -1,3 +1,19 @@
+2017-01-20  Martin Jambor  <mjambor@suse.cz>
+
+        * hsa.h: Renaed to hsa-common.h.  Adjusted a comment.
+        * hsa.c: Renaed to hsa-common.c.  Change include of gt-hsa.h to
+        gt-hsa-common.h.
+        * Makefile.in (OBJS): Rename hsa.o to hsa-common.o.
+        (GTFILES): Rename hsa.c to hsa-common.c.
+        * hsa-brig.c: Change include of hsa.h to hsa-common.h.
+        * hsa-dump.c: Likewise.
+        * hsa-gen.c: Likewise.
+        * hsa-regalloc.c: Likewise.
+        * ipa-hsa.c: Likewise.
+        * omp-expand.c: Likewise.
+        * omp-low.c: Likewise.
+        * toplev.c: Likewise.
+
 2017-01-20  Marek Polacek  <polacek@redhat.com>
 
        PR c/64279
index 7a7e27ac2955c227dfc0914c959d06a2ebf7aef6..df02246e31e3d37ed919b96016780db58d0d3afd 100644 (file)
@@ -1320,7 +1320,7 @@ OBJS = \
        haifa-sched.o \
        hash-map-tests.o \
        hash-set-tests.o \
-       hsa.o \
+       hsa-common.o \
        hsa-gen.o \
        hsa-regalloc.o \
        hsa-brig.o \
@@ -2508,7 +2508,7 @@ GTFILES = $(CPP_ID_DATA_H) $(srcdir)/input.h $(srcdir)/coretypes.h \
   $(srcdir)/sancov.c \
   $(srcdir)/ipa-devirt.c \
   $(srcdir)/internal-fn.h \
-  $(srcdir)/hsa.c \
+  $(srcdir)/hsa-common.c \
   @all_gtfiles@
 
 # Compute the list of GT header files from the corresponding C sources,
index 5fe302f25f5b0b1ed6e7ca847af7a192a4dc8aa2..1a2d45fcc527216c517d865dec5628ed5a9aec6d 100644 (file)
@@ -44,7 +44,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "dumpfile.h"
 #include "print-tree.h"
 #include "symbol-summary.h"
-#include "hsa.h"
+#include "hsa-common.h"
 #include "gomp-constants.h"
 
 /* Convert VAL to little endian form, if necessary.  */
diff --git a/gcc/hsa-common.c b/gcc/hsa-common.c
new file mode 100644 (file)
index 0000000..95636eb
--- /dev/null
@@ -0,0 +1,994 @@
+/* Implementation of commonly needed HSAIL related functions and methods.
+   Copyright (C) 2013-2017 Free Software Foundation, Inc.
+   Contributed by Martin Jambor <mjambor@suse.cz> and
+   Martin Liska <mliska@suse.cz>.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "is-a.h"
+#include "hash-set.h"
+#include "hash-map.h"
+#include "vec.h"
+#include "tree.h"
+#include "dumpfile.h"
+#include "gimple-pretty-print.h"
+#include "diagnostic-core.h"
+#include "alloc-pool.h"
+#include "cgraph.h"
+#include "print-tree.h"
+#include "stringpool.h"
+#include "symbol-summary.h"
+#include "hsa-common.h"
+#include "internal-fn.h"
+#include "ctype.h"
+#include "builtins.h"
+
+/* Structure containing intermediate HSA representation of the generated
+   function.  */
+class hsa_function_representation *hsa_cfun;
+
+/* Element of the mapping vector between a host decl and an HSA kernel.  */
+
+struct GTY(()) hsa_decl_kernel_map_element
+{
+  /* The decl of the host function.  */
+  tree decl;
+  /* Name of the HSA kernel in BRIG.  */
+  char * GTY((skip)) name;
+  /* Size of OMP data, if the kernel contains a kernel dispatch.  */
+  unsigned omp_data_size;
+  /* True if the function is gridified kernel.  */
+  bool gridified_kernel_p;
+};
+
+/* Mapping between decls and corresponding HSA kernels in this compilation
+   unit.  */
+
+static GTY (()) vec<hsa_decl_kernel_map_element, va_gc>
+  *hsa_decl_kernel_mapping;
+
+/* Mapping between decls and corresponding HSA kernels
+   called by the function.  */
+hash_map <tree, vec <const char *> *> *hsa_decl_kernel_dependencies;
+
+/* Hash function to lookup a symbol for a decl.  */
+hash_table <hsa_noop_symbol_hasher> *hsa_global_variable_symbols;
+
+/* HSA summaries.  */
+hsa_summary_t *hsa_summaries = NULL;
+
+/* HSA number of threads.  */
+hsa_symbol *hsa_num_threads = NULL;
+
+/* HSA function that cannot be expanded to HSAIL.  */
+hash_set <tree> *hsa_failed_functions = NULL;
+
+/* True if compilation unit-wide data are already allocated and initialized.  */
+static bool compilation_unit_data_initialized;
+
+/* Return true if FNDECL represents an HSA-callable function.  */
+
+bool
+hsa_callable_function_p (tree fndecl)
+{
+  return (lookup_attribute ("omp declare target", DECL_ATTRIBUTES (fndecl))
+         && !lookup_attribute ("oacc function", DECL_ATTRIBUTES (fndecl)));
+}
+
+/* Allocate HSA structures that are are used when dealing with different
+   functions.  */
+
+void
+hsa_init_compilation_unit_data (void)
+{
+  if (compilation_unit_data_initialized)
+    return;
+
+  compilation_unit_data_initialized = true;
+
+  hsa_global_variable_symbols = new hash_table <hsa_noop_symbol_hasher> (8);
+  hsa_failed_functions = new hash_set <tree> ();
+  hsa_emitted_internal_decls = new hash_table <hsa_internal_fn_hasher> (2);
+}
+
+/* Free data structures that are used when dealing with different
+   functions.  */
+
+void
+hsa_deinit_compilation_unit_data (void)
+{
+  gcc_assert (compilation_unit_data_initialized);
+
+  delete hsa_failed_functions;
+  delete hsa_emitted_internal_decls;
+
+  for (hash_table <hsa_noop_symbol_hasher>::iterator it
+       = hsa_global_variable_symbols->begin ();
+       it != hsa_global_variable_symbols->end ();
+       ++it)
+    {
+      hsa_symbol *sym = *it;
+      delete sym;
+    }
+
+  delete hsa_global_variable_symbols;
+
+  if (hsa_num_threads)
+    {
+      delete hsa_num_threads;
+      hsa_num_threads = NULL;
+    }
+
+  compilation_unit_data_initialized = false;
+}
+
+/* Return true if we are generating large HSA machine model.  */
+
+bool
+hsa_machine_large_p (void)
+{
+  /* FIXME: I suppose this is technically wrong but should work for me now.  */
+  return (GET_MODE_BITSIZE (Pmode) == 64);
+}
+
+/* Return the HSA profile we are using.  */
+
+bool
+hsa_full_profile_p (void)
+{
+  return true;
+}
+
+/* Return true if a register in operand number OPNUM of instruction
+   is an output.  False if it is an input.  */
+
+bool
+hsa_insn_basic::op_output_p (unsigned opnum)
+{
+  switch (m_opcode)
+    {
+    case HSA_OPCODE_PHI:
+    case BRIG_OPCODE_CBR:
+    case BRIG_OPCODE_SBR:
+    case BRIG_OPCODE_ST:
+    case BRIG_OPCODE_SIGNALNORET:
+    case BRIG_OPCODE_DEBUGTRAP:
+      /* FIXME: There are probably missing cases here, double check.  */
+      return false;
+    case BRIG_OPCODE_EXPAND:
+      /* Example: expand_v4_b32_b128 (dest0, dest1, dest2, dest3), src0.  */
+      return opnum < operand_count () - 1;
+    default:
+     return opnum == 0;
+    }
+}
+
+/* Return true if OPCODE is an floating-point bit instruction opcode.  */
+
+bool
+hsa_opcode_floating_bit_insn_p (BrigOpcode16_t opcode)
+{
+  switch (opcode)
+    {
+    case BRIG_OPCODE_NEG:
+    case BRIG_OPCODE_ABS:
+    case BRIG_OPCODE_CLASS:
+    case BRIG_OPCODE_COPYSIGN:
+      return true;
+    default:
+      return false;
+    }
+}
+
+/* Return the number of destination operands for this INSN.  */
+
+unsigned
+hsa_insn_basic::input_count ()
+{
+  switch (m_opcode)
+    {
+      default:
+       return 1;
+
+      case BRIG_OPCODE_NOP:
+       return 0;
+
+      case BRIG_OPCODE_EXPAND:
+       return 2;
+
+      case BRIG_OPCODE_LD:
+       /* ld_v[234] not yet handled.  */
+       return 1;
+
+      case BRIG_OPCODE_ST:
+       return 0;
+
+      case BRIG_OPCODE_ATOMICNORET:
+       return 0;
+
+      case BRIG_OPCODE_SIGNAL:
+       return 1;
+
+      case BRIG_OPCODE_SIGNALNORET:
+       return 0;
+
+      case BRIG_OPCODE_MEMFENCE:
+       return 0;
+
+      case BRIG_OPCODE_RDIMAGE:
+      case BRIG_OPCODE_LDIMAGE:
+      case BRIG_OPCODE_STIMAGE:
+      case BRIG_OPCODE_QUERYIMAGE:
+      case BRIG_OPCODE_QUERYSAMPLER:
+       sorry ("HSA image ops not handled");
+       return 0;
+
+      case BRIG_OPCODE_CBR:
+      case BRIG_OPCODE_BR:
+       return 0;
+
+      case BRIG_OPCODE_SBR:
+       return 0; /* ??? */
+
+      case BRIG_OPCODE_WAVEBARRIER:
+       return 0; /* ??? */
+
+      case BRIG_OPCODE_BARRIER:
+      case BRIG_OPCODE_ARRIVEFBAR:
+      case BRIG_OPCODE_INITFBAR:
+      case BRIG_OPCODE_JOINFBAR:
+      case BRIG_OPCODE_LEAVEFBAR:
+      case BRIG_OPCODE_RELEASEFBAR:
+      case BRIG_OPCODE_WAITFBAR:
+       return 0;
+
+      case BRIG_OPCODE_LDF:
+       return 1;
+
+      case BRIG_OPCODE_ACTIVELANECOUNT:
+      case BRIG_OPCODE_ACTIVELANEID:
+      case BRIG_OPCODE_ACTIVELANEMASK:
+      case BRIG_OPCODE_ACTIVELANEPERMUTE:
+       return 1; /* ??? */
+
+      case BRIG_OPCODE_CALL:
+      case BRIG_OPCODE_SCALL:
+      case BRIG_OPCODE_ICALL:
+       return 0;
+
+      case BRIG_OPCODE_RET:
+       return 0;
+
+      case BRIG_OPCODE_ALLOCA:
+       return 1;
+
+      case BRIG_OPCODE_CLEARDETECTEXCEPT:
+       return 0;
+
+      case BRIG_OPCODE_SETDETECTEXCEPT:
+       return 0;
+
+      case BRIG_OPCODE_PACKETCOMPLETIONSIG:
+      case BRIG_OPCODE_PACKETID:
+      case BRIG_OPCODE_CASQUEUEWRITEINDEX:
+      case BRIG_OPCODE_LDQUEUEREADINDEX:
+      case BRIG_OPCODE_LDQUEUEWRITEINDEX:
+      case BRIG_OPCODE_STQUEUEREADINDEX:
+      case BRIG_OPCODE_STQUEUEWRITEINDEX:
+       return 1; /* ??? */
+
+      case BRIG_OPCODE_ADDQUEUEWRITEINDEX:
+       return 1;
+
+      case BRIG_OPCODE_DEBUGTRAP:
+       return 0;
+
+      case BRIG_OPCODE_GROUPBASEPTR:
+      case BRIG_OPCODE_KERNARGBASEPTR:
+       return 1; /* ??? */
+
+      case HSA_OPCODE_ARG_BLOCK:
+       return 0;
+
+      case BRIG_KIND_DIRECTIVE_COMMENT:
+       return 0;
+    }
+}
+
+/* Return the number of source operands for this INSN.  */
+
+unsigned
+hsa_insn_basic::num_used_ops ()
+{
+  gcc_checking_assert (input_count () <= operand_count ());
+
+  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 < m_align)
+    {
+      fprintf (dump_file, "Decreasing alignment to %u in instruction ", value);
+      dump_hsa_insn (dump_file, this);
+    }
+  m_align = value;
+}
+
+/* Return size of HSA type T in bits.  */
+
+unsigned
+hsa_type_bit_size (BrigType16_t t)
+{
+  switch (t)
+    {
+    case BRIG_TYPE_B1:
+      return 1;
+
+    case BRIG_TYPE_U8:
+    case BRIG_TYPE_S8:
+    case BRIG_TYPE_B8:
+      return 8;
+
+    case BRIG_TYPE_U16:
+    case BRIG_TYPE_S16:
+    case BRIG_TYPE_B16:
+    case BRIG_TYPE_F16:
+      return 16;
+
+    case BRIG_TYPE_U32:
+    case BRIG_TYPE_S32:
+    case BRIG_TYPE_B32:
+    case BRIG_TYPE_F32:
+    case BRIG_TYPE_U8X4:
+    case BRIG_TYPE_U16X2:
+    case BRIG_TYPE_S8X4:
+    case BRIG_TYPE_S16X2:
+    case BRIG_TYPE_F16X2:
+      return 32;
+
+    case BRIG_TYPE_U64:
+    case BRIG_TYPE_S64:
+    case BRIG_TYPE_F64:
+    case BRIG_TYPE_B64:
+    case BRIG_TYPE_U8X8:
+    case BRIG_TYPE_U16X4:
+    case BRIG_TYPE_U32X2:
+    case BRIG_TYPE_S8X8:
+    case BRIG_TYPE_S16X4:
+    case BRIG_TYPE_S32X2:
+    case BRIG_TYPE_F16X4:
+    case BRIG_TYPE_F32X2:
+
+      return 64;
+
+    case BRIG_TYPE_B128:
+    case BRIG_TYPE_U8X16:
+    case BRIG_TYPE_U16X8:
+    case BRIG_TYPE_U32X4:
+    case BRIG_TYPE_U64X2:
+    case BRIG_TYPE_S8X16:
+    case BRIG_TYPE_S16X8:
+    case BRIG_TYPE_S32X4:
+    case BRIG_TYPE_S64X2:
+    case BRIG_TYPE_F16X8:
+    case BRIG_TYPE_F32X4:
+    case BRIG_TYPE_F64X2:
+      return 128;
+
+    default:
+      gcc_assert (hsa_seen_error ());
+      return t;
+    }
+}
+
+/* Return BRIG bit-type with BITSIZE length.  */
+
+BrigType16_t
+hsa_bittype_for_bitsize (unsigned bitsize)
+{
+  switch (bitsize)
+    {
+    case 1:
+      return BRIG_TYPE_B1;
+    case 8:
+      return BRIG_TYPE_B8;
+    case 16:
+      return BRIG_TYPE_B16;
+    case 32:
+      return BRIG_TYPE_B32;
+    case 64:
+      return BRIG_TYPE_B64;
+    case 128:
+      return BRIG_TYPE_B128;
+    default:
+      gcc_unreachable ();
+    }
+}
+
+/* Return BRIG unsigned int type with BITSIZE length.  */
+
+BrigType16_t
+hsa_uint_for_bitsize (unsigned bitsize)
+{
+  switch (bitsize)
+    {
+    case 8:
+      return BRIG_TYPE_U8;
+    case 16:
+      return BRIG_TYPE_U16;
+    case 32:
+      return BRIG_TYPE_U32;
+    case 64:
+      return BRIG_TYPE_U64;
+    default:
+      gcc_unreachable ();
+    }
+}
+
+/* Return BRIG float type with BITSIZE length.  */
+
+BrigType16_t
+hsa_float_for_bitsize (unsigned bitsize)
+{
+  switch (bitsize)
+    {
+    case 16:
+      return BRIG_TYPE_F16;
+    case 32:
+      return BRIG_TYPE_F32;
+    case 64:
+      return BRIG_TYPE_F64;
+    default:
+      gcc_unreachable ();
+    }
+}
+
+/* Return HSA bit-type with the same size as the type T.  */
+
+BrigType16_t
+hsa_bittype_for_type (BrigType16_t t)
+{
+  return hsa_bittype_for_bitsize (hsa_type_bit_size (t));
+}
+
+/* Return HSA unsigned integer type with the same size as the type T.  */
+
+BrigType16_t
+hsa_unsigned_type_for_type (BrigType16_t t)
+{
+  return hsa_uint_for_bitsize (hsa_type_bit_size (t));
+}
+
+/* Return true if TYPE is a packed HSA type.  */
+
+bool
+hsa_type_packed_p (BrigType16_t type)
+{
+  return (type & BRIG_TYPE_PACK_MASK) != BRIG_TYPE_PACK_NONE;
+}
+
+/* Return true if and only if TYPE is a floating point number type.  */
+
+bool
+hsa_type_float_p (BrigType16_t type)
+{
+  switch (type & BRIG_TYPE_BASE_MASK)
+    {
+    case BRIG_TYPE_F16:
+    case BRIG_TYPE_F32:
+    case BRIG_TYPE_F64:
+      return true;
+    default:
+      return false;
+    }
+}
+
+/* Return true if and only if TYPE is an integer number type.  */
+
+bool
+hsa_type_integer_p (BrigType16_t type)
+{
+  switch (type & BRIG_TYPE_BASE_MASK)
+    {
+    case BRIG_TYPE_U8:
+    case BRIG_TYPE_U16:
+    case BRIG_TYPE_U32:
+    case BRIG_TYPE_U64:
+    case BRIG_TYPE_S8:
+    case BRIG_TYPE_S16:
+    case BRIG_TYPE_S32:
+    case BRIG_TYPE_S64:
+      return true;
+    default:
+      return false;
+    }
+}
+
+/* Return true if and only if TYPE is an bit-type.  */
+
+bool
+hsa_btype_p (BrigType16_t type)
+{
+  switch (type & BRIG_TYPE_BASE_MASK)
+    {
+    case BRIG_TYPE_B8:
+    case BRIG_TYPE_B16:
+    case BRIG_TYPE_B32:
+    case BRIG_TYPE_B64:
+    case BRIG_TYPE_B128:
+      return true;
+    default:
+      return false;
+    }
+}
+
+
+/* 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 HSA alignment encoding alignment of T got
+   by get_object_alignment.  */
+
+BrigAlignment8_t
+hsa_object_alignment (tree t)
+{
+  return hsa_alignment_encoding (get_object_alignment (t));
+}
+
+/* Return byte alignment for given BrigAlignment8_t value.  */
+
+unsigned
+hsa_byte_alignment (BrigAlignment8_t alignment)
+{
+  gcc_assert (alignment != BRIG_ALIGNMENT_NONE);
+
+  return 1 << (alignment - 1);
+}
+
+/* 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 of a HSA instruction.  */
+
+void
+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_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))
+    mem->~hsa_insn_mem ();
+  else if (hsa_insn_atomic *atomic = dyn_cast <hsa_insn_atomic *> (insn))
+    atomic->~hsa_insn_atomic ();
+  else if (hsa_insn_seg *seg = dyn_cast <hsa_insn_seg *> (insn))
+    seg->~hsa_insn_seg ();
+  else if (hsa_insn_call *call = dyn_cast <hsa_insn_call *> (insn))
+    call->~hsa_insn_call ();
+  else if (hsa_insn_arg_block *block = dyn_cast <hsa_insn_arg_block *> (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
+    insn->~hsa_insn_basic ();
+}
+
+/* Call the correct destructor of a HSA operand.  */
+
+void
+hsa_destroy_operand (hsa_op_base *op)
+{
+  if (hsa_op_code_list *list = dyn_cast <hsa_op_code_list *> (op))
+    list->~hsa_op_code_list ();
+  else if (hsa_op_operand_list *list = dyn_cast <hsa_op_operand_list *> (op))
+    list->~hsa_op_operand_list ();
+  else if (hsa_op_reg *reg = dyn_cast <hsa_op_reg *> (op))
+    reg->~hsa_op_reg ();
+  else if (hsa_op_immed *immed = dyn_cast <hsa_op_immed *> (op))
+    immed->~hsa_op_immed ();
+  else
+    op->~hsa_op_base ();
+}
+
+/* Create a mapping between the original function DECL and kernel name NAME.  */
+
+void
+hsa_add_kern_decl_mapping (tree decl, char *name, unsigned omp_data_size,
+                          bool gridified_kernel_p)
+{
+  hsa_decl_kernel_map_element dkm;
+  dkm.decl = decl;
+  dkm.name = name;
+  dkm.omp_data_size = omp_data_size;
+  dkm.gridified_kernel_p = gridified_kernel_p;
+  vec_safe_push (hsa_decl_kernel_mapping, dkm);
+}
+
+/* Return the number of kernel decl name mappings.  */
+
+unsigned
+hsa_get_number_decl_kernel_mappings (void)
+{
+  return vec_safe_length (hsa_decl_kernel_mapping);
+}
+
+/* Return the decl in the Ith kernel decl name mapping.  */
+
+tree
+hsa_get_decl_kernel_mapping_decl (unsigned i)
+{
+  return (*hsa_decl_kernel_mapping)[i].decl;
+}
+
+/* Return the name in the Ith kernel decl name mapping.  */
+
+char *
+hsa_get_decl_kernel_mapping_name (unsigned i)
+{
+  return (*hsa_decl_kernel_mapping)[i].name;
+}
+
+/* Return maximum OMP size for kernel decl name mapping.  */
+
+unsigned
+hsa_get_decl_kernel_mapping_omp_size (unsigned i)
+{
+  return (*hsa_decl_kernel_mapping)[i].omp_data_size;
+}
+
+/* Return if the function is gridified kernel in decl name mapping.  */
+
+bool
+hsa_get_decl_kernel_mapping_gridified (unsigned i)
+{
+  return (*hsa_decl_kernel_mapping)[i].gridified_kernel_p;
+}
+
+/* Free the mapping between original decls and kernel names.  */
+
+void
+hsa_free_decl_kernel_mapping (void)
+{
+  if (hsa_decl_kernel_mapping == NULL)
+    return;
+
+  for (unsigned i = 0; i < hsa_decl_kernel_mapping->length (); ++i)
+    free ((*hsa_decl_kernel_mapping)[i].name);
+  ggc_free (hsa_decl_kernel_mapping);
+}
+
+/* Add new kernel dependency.  */
+
+void
+hsa_add_kernel_dependency (tree caller, const char *called_function)
+{
+  if (hsa_decl_kernel_dependencies == NULL)
+    hsa_decl_kernel_dependencies = new hash_map<tree, vec<const char *> *> ();
+
+  vec <const char *> *s = NULL;
+  vec <const char *> **slot = hsa_decl_kernel_dependencies->get (caller);
+  if (slot == NULL)
+    {
+      s = new vec <const char *> ();
+      hsa_decl_kernel_dependencies->put (caller, s);
+    }
+  else
+    s = *slot;
+
+  s->safe_push (called_function);
+}
+
+/* Expansion to HSA needs a few gc roots to hold types, constructors etc.  In
+   order to minimize the number of GTY roots, we'll root them all in the
+   following array.  The individual elements should only be accessed by the
+   very simple getters (of a pointer-to-tree) below.  */
+
+static GTY(()) tree hsa_tree_gt_roots[3];
+
+tree *
+hsa_get_ctor_statements (void)
+{
+  return &hsa_tree_gt_roots[0];
+}
+
+tree *
+hsa_get_dtor_statements (void)
+{
+  return &hsa_tree_gt_roots[1];
+}
+
+tree *
+hsa_get_kernel_dispatch_type (void)
+{
+  return &hsa_tree_gt_roots[2];
+}
+
+/* Modify the name P in-place so that it is a valid HSA identifier.  */
+
+void
+hsa_sanitize_name (char *p)
+{
+  for (; *p; p++)
+    if (*p == '.' || *p == '-')
+      *p = '_';
+}
+
+/* Clone the name P, set trailing ampersand and sanitize the name.  */
+
+char *
+hsa_brig_function_name (const char *p)
+{
+  unsigned len = strlen (p);
+  char *buf = XNEWVEC (char, len + 2);
+
+  buf[0] = '&';
+  buf[len + 1] = '\0';
+  memcpy (buf + 1, p, len);
+
+  hsa_sanitize_name (buf);
+  return buf;
+}
+
+/* Add a flatten attribute and disable vectorization for gpu implementation
+   function decl GDECL.  */
+
+void hsa_summary_t::process_gpu_implementation_attributes (tree gdecl)
+{
+  DECL_ATTRIBUTES (gdecl)
+    = tree_cons (get_identifier ("flatten"), NULL_TREE,
+                DECL_ATTRIBUTES (gdecl));
+
+  tree fn_opts = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (gdecl);
+  if (fn_opts == NULL_TREE)
+    fn_opts = optimization_default_node;
+  fn_opts = copy_node (fn_opts);
+  TREE_OPTIMIZATION (fn_opts)->x_flag_tree_loop_vectorize = false;
+  TREE_OPTIMIZATION (fn_opts)->x_flag_tree_slp_vectorize = false;
+  DECL_FUNCTION_SPECIFIC_OPTIMIZATION (gdecl) = fn_opts;
+}
+
+void
+hsa_summary_t::link_functions (cgraph_node *gpu, cgraph_node *host,
+                              hsa_function_kind kind, bool gridified_kernel_p)
+{
+  hsa_function_summary *gpu_summary = get (gpu);
+  hsa_function_summary *host_summary = get (host);
+
+  gpu_summary->m_kind = kind;
+  host_summary->m_kind = kind;
+
+  gpu_summary->m_gpu_implementation_p = true;
+  host_summary->m_gpu_implementation_p = false;
+
+  gpu_summary->m_gridified_kernel_p = gridified_kernel_p;
+  host_summary->m_gridified_kernel_p = gridified_kernel_p;
+
+  gpu_summary->m_bound_function = host;
+  host_summary->m_bound_function = gpu;
+
+  process_gpu_implementation_attributes (gpu->decl);
+
+  /* Create reference between a kernel and a corresponding host implementation
+     to quarantee LTO streaming to a same LTRANS.  */
+  if (kind == HSA_KERNEL)
+    gpu->create_reference (host, IPA_REF_ADDR);
+}
+
+/* Add a HOST function to HSA summaries.  */
+
+void
+hsa_register_kernel (cgraph_node *host)
+{
+  if (hsa_summaries == NULL)
+    hsa_summaries = new hsa_summary_t (symtab);
+  hsa_function_summary *s = hsa_summaries->get (host);
+  s->m_kind = HSA_KERNEL;
+}
+
+/* Add a pair of functions to HSA summaries.  GPU is an HSA implementation of
+   a HOST function.  */
+
+void
+hsa_register_kernel (cgraph_node *gpu, cgraph_node *host)
+{
+  if (hsa_summaries == NULL)
+    hsa_summaries = new hsa_summary_t (symtab);
+  hsa_summaries->link_functions (gpu, host, HSA_KERNEL, true);
+}
+
+/* Return true if expansion of the current HSA function has already failed.  */
+
+bool
+hsa_seen_error (void)
+{
+  return hsa_cfun->m_seen_error;
+}
+
+/* Mark current HSA function as failed.  */
+
+void
+hsa_fail_cfun (void)
+{
+  hsa_failed_functions->add (hsa_cfun->m_decl);
+  hsa_cfun->m_seen_error = true;
+}
+
+char *
+hsa_internal_fn::name ()
+{
+  char *name = xstrdup (internal_fn_name (m_fn));
+  for (char *ptr = name; *ptr; ptr++)
+    *ptr = TOLOWER (*ptr);
+
+  const char *suffix = NULL;
+  if (m_type_bit_size == 32)
+    suffix = "f";
+
+  if (suffix)
+    {
+      char *name2 = concat (name, suffix, NULL);
+      free (name);
+      name = name2;
+    }
+
+  hsa_sanitize_name (name);
+  return name;
+}
+
+unsigned
+hsa_internal_fn::get_arity ()
+{
+  switch (m_fn)
+    {
+    case IFN_ACOS:
+    case IFN_ASIN:
+    case IFN_ATAN:
+    case IFN_COS:
+    case IFN_EXP:
+    case IFN_EXP10:
+    case IFN_EXP2:
+    case IFN_EXPM1:
+    case IFN_LOG:
+    case IFN_LOG10:
+    case IFN_LOG1P:
+    case IFN_LOG2:
+    case IFN_LOGB:
+    case IFN_SIGNIFICAND:
+    case IFN_SIN:
+    case IFN_SQRT:
+    case IFN_TAN:
+    case IFN_CEIL:
+    case IFN_FLOOR:
+    case IFN_NEARBYINT:
+    case IFN_RINT:
+    case IFN_ROUND:
+    case IFN_TRUNC:
+      return 1;
+    case IFN_ATAN2:
+    case IFN_COPYSIGN:
+    case IFN_FMOD:
+    case IFN_POW:
+    case IFN_REMAINDER:
+    case IFN_SCALB:
+    case IFN_LDEXP:
+      return 2;
+    case IFN_CLRSB:
+    case IFN_CLZ:
+    case IFN_CTZ:
+    case IFN_FFS:
+    case IFN_PARITY:
+    case IFN_POPCOUNT:
+    default:
+      /* As we produce sorry message for unknown internal functions,
+        reaching this label is definitely a bug.  */
+      gcc_unreachable ();
+    }
+}
+
+BrigType16_t
+hsa_internal_fn::get_argument_type (int n)
+{
+  switch (m_fn)
+    {
+    case IFN_ACOS:
+    case IFN_ASIN:
+    case IFN_ATAN:
+    case IFN_COS:
+    case IFN_EXP:
+    case IFN_EXP10:
+    case IFN_EXP2:
+    case IFN_EXPM1:
+    case IFN_LOG:
+    case IFN_LOG10:
+    case IFN_LOG1P:
+    case IFN_LOG2:
+    case IFN_LOGB:
+    case IFN_SIGNIFICAND:
+    case IFN_SIN:
+    case IFN_SQRT:
+    case IFN_TAN:
+    case IFN_CEIL:
+    case IFN_FLOOR:
+    case IFN_NEARBYINT:
+    case IFN_RINT:
+    case IFN_ROUND:
+    case IFN_TRUNC:
+    case IFN_ATAN2:
+    case IFN_COPYSIGN:
+    case IFN_FMOD:
+    case IFN_POW:
+    case IFN_REMAINDER:
+    case IFN_SCALB:
+      return hsa_float_for_bitsize (m_type_bit_size);
+    case IFN_LDEXP:
+      {
+       if (n == -1 || n == 0)
+         return hsa_float_for_bitsize (m_type_bit_size);
+       else
+         return BRIG_TYPE_S32;
+      }
+    default:
+      /* As we produce sorry message for unknown internal functions,
+        reaching this label is definitely a bug.  */
+      gcc_unreachable ();
+    }
+}
+
+#include "gt-hsa-common.h"
diff --git a/gcc/hsa-common.h b/gcc/hsa-common.h
new file mode 100644 (file)
index 0000000..a24bf6e
--- /dev/null
@@ -0,0 +1,1412 @@
+/* HSAIL and BRIG related macros and definitions.
+   Copyright (C) 2013-2017 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef HSA_H
+#define HSA_H
+
+#include "hsa-brig-format.h"
+#include "is-a.h"
+#include "predict.h"
+#include "tree.h"
+#include "vec.h"
+#include "hash-table.h"
+#include "basic-block.h"
+
+
+/* Return true if the compiler should produce HSAIL.  */
+
+static inline bool
+hsa_gen_requested_p (void)
+{
+#ifndef ENABLE_HSA
+  return false;
+#endif
+  return !flag_disable_hsa;
+}
+
+/* Standard warning message if we failed to generate HSAIL for a function.  */
+
+#define HSA_SORRY_MSG "could not emit HSAIL for the function"
+
+class hsa_op_immed;
+class hsa_op_cst_list;
+class hsa_insn_basic;
+class hsa_op_address;
+class hsa_op_reg;
+class hsa_bb;
+
+/* Class representing an input argument, output argument (result) or a
+   variable, that will eventually end up being a symbol directive.  */
+
+struct hsa_symbol
+{
+  /* Constructor.  */
+  hsa_symbol (BrigType16_t type, BrigSegment8_t segment,
+             BrigLinkage8_t linkage, bool global_scope_p = false,
+             BrigAllocation allocation = BRIG_ALLOCATION_AUTOMATIC,
+             BrigAlignment8_t align = BRIG_ALIGNMENT_8);
+
+  /* Return total size of the symbol.  */
+  unsigned HOST_WIDE_INT total_byte_size ();
+
+  /* Fill in those values into the symbol according to DECL, which are
+     determined independently from whether it is parameter, result,
+     or a variable, local or global.  */
+  void fillup_for_decl (tree decl);
+
+  /* Pointer to the original tree, which is PARM_DECL for input parameters and
+     RESULT_DECL for the output parameters.  Also can be CONST_DECL for Fortran
+     constants which need to be put into readonly segment.  */
+  tree m_decl;
+
+  /* Name of the symbol, that will be written into output and dumps.  Can be
+     NULL, see name_number below.  */
+  const char *m_name;
+
+  /* If name is NULL, artificial name will be formed from the segment name and
+     this number.  */
+  int m_name_number;
+
+  /* Once written, this is the offset of the associated symbol directive.  Zero
+     means the symbol has not been written yet.  */
+  unsigned m_directive_offset;
+
+  /* HSA type of the parameter.  */
+  BrigType16_t m_type;
+
+  /* The HSA segment this will eventually end up in.  */
+  BrigSegment8_t m_segment;
+
+  /* The HSA kind of linkage.  */
+  BrigLinkage8_t m_linkage;
+
+  /* Array dimension, if non-zero.  */
+  unsigned HOST_WIDE_INT m_dim;
+
+  /* Constant value, used for string constants.  */
+  hsa_op_immed *m_cst_value;
+
+  /* Is in global scope.  */
+  bool m_global_scope_p;
+
+  /* True if an error has been seen for the symbol.  */
+  bool m_seen_error;
+
+  /* Symbol allocation.  */
+  BrigAllocation m_allocation;
+
+  /* Flag used for global variables if a variable is already emitted or not.  */
+  bool m_emitted_to_brig;
+
+  /* Alignment of the symbol.  */
+  BrigAlignment8_t m_align;
+
+private:
+  /* Default constructor.  */
+  hsa_symbol ();
+};
+
+/* Abstract class for HSA instruction operands.  */
+
+class hsa_op_base
+{
+public:
+  /* Next operand scheduled to be written when writing BRIG operand
+     section.  */
+  hsa_op_base *m_next;
+
+  /* Offset to which the associated operand structure will be written.  Zero if
+     yet not scheduled for writing.  */
+  unsigned m_brig_op_offset;
+
+  /* The type of a particular operand.  */
+  BrigKind16_t m_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.  */
+
+class hsa_op_with_type : public hsa_op_base
+{
+public:
+  /* The type.  */
+  BrigType16_t m_type;
+
+  /* Convert an operand to a destination type DTYPE and attach insns
+     to HBB if needed.  */
+  hsa_op_with_type *get_in_type (BrigType16_t dtype, hsa_bb *hbb);
+
+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.  */
+
+class hsa_op_immed : public hsa_op_with_type
+{
+public:
+  hsa_op_immed (tree tree_val, bool min32int = true);
+  hsa_op_immed (HOST_WIDE_INT int_value, BrigType16_t type);
+  void *operator new (size_t);
+  ~hsa_op_immed ();
+  void set_type (BrigKind16_t t);
+
+  /* Function returns pointer to a buffer that contains binary representation
+     of the immeadiate value.  The buffer has length of BRIG_SIZE and
+     a caller is responsible for deallocation of the buffer.  */
+  char *emit_to_buffer (unsigned *brig_size);
+
+  /* Value as represented by middle end.  */
+  tree m_tree_value;
+
+  /* Integer value representation.  */
+  HOST_WIDE_INT m_int_value;
+
+private:
+  /* Make the default constructor inaccessible.  */
+  hsa_op_immed ();
+  /* 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.  */
+
+template <>
+template <>
+inline bool
+is_a_helper <hsa_op_immed *>::test (hsa_op_base *p)
+{
+  return p->m_kind == BRIG_KIND_OPERAND_CONSTANT_BYTES;
+}
+
+/* Likewise, but for a more specified base. */
+
+template <>
+template <>
+inline bool
+is_a_helper <hsa_op_immed *>::test (hsa_op_with_type *p)
+{
+  return p->m_kind == BRIG_KIND_OPERAND_CONSTANT_BYTES;
+}
+
+
+/* HSA register operand.  */
+
+class hsa_op_reg : public hsa_op_with_type
+{
+  friend class hsa_insn_basic;
+  friend class hsa_insn_phi;
+public:
+  hsa_op_reg (BrigType16_t t);
+  void *operator new (size_t);
+
+  /* Verify register operand.  */
+  void verify_ssa ();
+
+  /* If NON-NULL, gimple SSA that we come from.  NULL if none.  */
+  tree m_gimple_ssa;
+
+  /* Defining instruction while still in the SSA.  */
+  hsa_insn_basic *m_def_insn;
+
+  /* If the register allocator decides to spill the register, this is the
+     appropriate spill symbol.  */
+  hsa_symbol *m_spill_sym;
+
+  /* Number of this register structure in the order in which they were
+     allocated.  */
+  int m_order;
+  int m_lr_begin, m_lr_end;
+
+  /* Zero if the register is not yet allocated.  After, allocation, this must
+     be 'c', 's', 'd' or 'q'.  */
+  char m_reg_class;
+  /* If allocated, the number of the HW register (within its HSA register
+     class).  */
+  char m_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 *) {}
+  /* Set definition where the register is defined.  */
+  void set_definition (hsa_insn_basic *insn);
+  /* Uses of the value while still in SSA.  */
+  auto_vec <hsa_insn_basic *> m_uses;
+};
+
+/* Report whether or not P is a register operand.  */
+
+template <>
+template <>
+inline bool
+is_a_helper <hsa_op_reg *>::test (hsa_op_base *p)
+{
+  return p->m_kind == BRIG_KIND_OPERAND_REGISTER;
+}
+
+/* Report whether or not P is a register operand.  */
+
+template <>
+template <>
+inline bool
+is_a_helper <hsa_op_reg *>::test (hsa_op_with_type *p)
+{
+  return p->m_kind == BRIG_KIND_OPERAND_REGISTER;
+}
+
+/* An address HSA operand.  */
+
+class hsa_op_address : public hsa_op_base
+{
+public:
+  /* 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.  */
+  hsa_op_address (hsa_symbol *sym, hsa_op_reg *reg,
+                 HOST_WIDE_INT offset = 0);
+
+  void *operator new (size_t);
+
+  /* Set up a new address operand consisting of base symbol SYM and
+     immediate OFFSET.  If the machine model is not large and offset is 64 bit,
+     the upper, 32 bits have to be zero.  */
+  hsa_op_address (hsa_symbol *sym, HOST_WIDE_INT offset = 0);
+
+  /* Set up a new address operand consisting of 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.  */
+  hsa_op_address (hsa_op_reg *reg, HOST_WIDE_INT offset = 0);
+
+  /* Symbol base of the address.  Can be NULL if there is none.  */
+  hsa_symbol *m_symbol;
+
+  /* Register offset.  Can be NULL if there is none.  */
+  hsa_op_reg *m_reg;
+
+  /* Immediate byte offset.  */
+  HOST_WIDE_INT m_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.  */
+
+template <>
+template <>
+inline bool
+is_a_helper <hsa_op_address *>::test (hsa_op_base *p)
+{
+  return p->m_kind == BRIG_KIND_OPERAND_ADDRESS;
+}
+
+/* A reference to code HSA operand.  It can be either reference
+   to a start of a BB or a start of a function.  */
+
+class hsa_op_code_ref : public hsa_op_base
+{
+public:
+  hsa_op_code_ref ();
+
+  /* Offset in the code section that this refers to.  */
+  unsigned m_directive_offset;
+};
+
+/* Report whether or not P is a code reference operand.  */
+
+template <>
+template <>
+inline bool
+is_a_helper <hsa_op_code_ref *>::test (hsa_op_base *p)
+{
+  return p->m_kind == BRIG_KIND_OPERAND_CODE_REF;
+}
+
+/* Code list HSA operand.  */
+
+class hsa_op_code_list: public hsa_op_base
+{
+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> m_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.  */
+
+template <>
+template <>
+inline bool
+is_a_helper <hsa_op_code_list *>::test (hsa_op_base *p)
+{
+  return p->m_kind == BRIG_KIND_OPERAND_CODE_LIST;
+}
+
+/* Operand list HSA operand.  */
+
+class hsa_op_operand_list: public hsa_op_base
+{
+public:
+  hsa_op_operand_list (unsigned elements);
+  ~hsa_op_operand_list ();
+  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> m_offsets;
+private:
+  /* Make the default constructor inaccessible.  */
+  hsa_op_operand_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.  */
+
+template <>
+template <>
+inline bool
+is_a_helper <hsa_op_operand_list *>::test (hsa_op_base *p)
+{
+  return p->m_kind == BRIG_KIND_OPERAND_OPERAND_LIST;
+}
+
+/* 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_ARG_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.  */
+
+class hsa_insn_basic
+{
+public:
+  hsa_insn_basic (unsigned nops, int opc);
+  hsa_insn_basic (unsigned nops, int opc, BrigType16_t t,
+                 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);
+  void set_op (int index, hsa_op_base *op);
+  hsa_op_base *get_op (int index);
+  hsa_op_base **get_op_addr (int index);
+  unsigned int operand_count ();
+  void verify ();
+  unsigned input_count ();
+  unsigned num_used_ops ();
+  void set_output_in_type (hsa_op_reg *dest, unsigned op_index, hsa_bb *hbb);
+  bool op_output_p (unsigned opnum);
+
+  /* The previous and next instruction in the basic block.  */
+  hsa_insn_basic *m_prev, *m_next;
+
+  /* Basic block this instruction belongs to.  */
+  basic_block m_bb;
+
+  /* Operand code distinguishing different types of instructions.  Eventually
+     these should only be BRIG_INST_* values from the BrigOpcode16_t range but
+     initially we use negative values for PHI nodes and such.  */
+  int m_opcode;
+
+  /* Linearized number assigned to the instruction by HSA RA.  */
+  int m_number;
+
+  /* Type of the destination of the operations.  */
+  BrigType16_t m_type;
+
+  /* BRIG offset of the instruction in code section.  */
+  unsigned int m_brig_offset;
+
+private:
+  /* 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 *) {}
+  /* 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> m_operands;
+};
+
+/* Class representing a PHI node of the SSA form of HSA virtual
+   registers.  */
+
+class hsa_insn_phi : public hsa_insn_basic
+{
+public:
+  hsa_insn_phi (unsigned nops, hsa_op_reg *dst);
+
+  /* Destination.  */
+  hsa_op_reg *m_dest;
+
+private:
+  /* Make the default constructor inaccessible.  */
+  hsa_insn_phi () : hsa_insn_basic (1, HSA_OPCODE_PHI) {}
+};
+
+/* Report whether or not P is a PHI node.  */
+
+template <>
+template <>
+inline bool
+is_a_helper <hsa_insn_phi *>::test (hsa_insn_basic *p)
+{
+  return p->m_opcode == HSA_OPCODE_PHI;
+}
+
+/* HSA instruction for  */
+class hsa_insn_br : public hsa_insn_basic
+{
+public:
+  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);
+
+  /* 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 (0, BRIG_OPCODE_BR) {}
+};
+
+/* 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_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);
+
+private:
+  /* Make the default constructor inaccessible.  */
+  hsa_insn_cbr () : hsa_insn_br (0, BRIG_OPCODE_CBR, BRIG_TYPE_B1,
+                                BRIG_WIDTH_1) {}
+};
+
+/* 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.  */
+
+class hsa_insn_sbr : public hsa_insn_basic
+{
+public:
+  hsa_insn_sbr (hsa_op_reg *index, unsigned jump_count);
+
+  /* Default destructor.  */
+  ~hsa_insn_sbr ();
+
+  void replace_all_labels (basic_block old_bb, basic_block new_bb);
+
+  /* Width as described in HSA documentation.  */
+  BrigWidth8_t m_width;
+
+  /* Jump table.  */
+  vec <basic_block> m_jump_table;
+
+  /* Code list for label references.  */
+  hsa_op_code_list *m_label_code_list;
+
+private:
+  /* Make the default constructor inaccessible.  */
+  hsa_insn_sbr () : hsa_insn_basic (1, BRIG_OPCODE_SBR) {}
+};
+
+/* Report whether P is a switch branching instruction.  */
+
+template <>
+template <>
+inline bool
+is_a_helper <hsa_insn_sbr *>::test (hsa_insn_basic *p)
+{
+  return p->m_opcode == BRIG_OPCODE_SBR;
+}
+
+/* HSA instruction for comparisons.  */
+
+class hsa_insn_cmp : public hsa_insn_basic
+{
+public:
+  hsa_insn_cmp (BrigCompareOperation8_t cmp, BrigType16_t t,
+               hsa_op_base *arg0 = NULL, hsa_op_base *arg1 = NULL,
+               hsa_op_base *arg2 = NULL);
+
+  /* Source type should be derived from operand types.  */
+
+  /* The comparison operation.  */
+  BrigCompareOperation8_t m_compare;
+
+  /* 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) {}
+};
+
+/* Report whether or not P is a comparison instruction.  */
+
+template <>
+template <>
+inline bool
+is_a_helper <hsa_insn_cmp *>::test (hsa_insn_basic *p)
+{
+  return p->m_opcode == BRIG_OPCODE_CMP;
+}
+
+/* HSA instruction for memory operations.  */
+
+class hsa_insn_mem : public hsa_insn_basic
+{
+public:
+  hsa_insn_mem (int opc, BrigType16_t t, hsa_op_base *arg0, hsa_op_base *arg1);
+
+  /* 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 m_align;
+
+  /* HSA equiv class, basically an alias set number.  */
+  uint8_t m_equiv_class;
+
+  /* TODO:  Add width modifier, perhaps also other things.  */
+protected:
+  hsa_insn_mem (unsigned nops, int opc, BrigType16_t t,
+               hsa_op_base *arg0 = NULL, hsa_op_base *arg1 = NULL,
+               hsa_op_base *arg2 = NULL, hsa_op_base *arg3 = NULL);
+
+private:
+  /* Make the default constructor inaccessible.  */
+  hsa_insn_mem () : hsa_insn_basic (1, BRIG_OPCODE_LD) {}
+};
+
+/* Report whether or not P is a memory instruction.  */
+
+template <>
+template <>
+inline bool
+is_a_helper <hsa_insn_mem *>::test (hsa_insn_basic *p)
+{
+  return (p->m_opcode == BRIG_OPCODE_LD
+         || p->m_opcode == BRIG_OPCODE_ST);
+}
+
+/* HSA instruction for atomic operations.  */
+
+class hsa_insn_atomic : public hsa_insn_mem
+{
+public:
+  hsa_insn_atomic (int nops, int opc, enum BrigAtomicOperation aop,
+                  BrigType16_t t, BrigMemoryOrder memorder,
+                  hsa_op_base *arg0 = NULL, hsa_op_base *arg1 = NULL,
+                  hsa_op_base *arg2 = NULL, hsa_op_base *arg3 = NULL);
+
+  /* The operation itself.  */
+  enum BrigAtomicOperation m_atomicop;
+
+  /* Things like acquire/release/aligned.  */
+  enum BrigMemoryOrder m_memoryorder;
+
+  /* Scope of the atomic operation.  */
+  enum BrigMemoryScope m_memoryscope;
+
+private:
+  /* Make the default constructor inaccessible.  */
+  hsa_insn_atomic () : hsa_insn_mem (1, BRIG_KIND_NONE, BRIG_TYPE_NONE) {}
+};
+
+/* Report whether or not P is an atomic instruction.  */
+
+template <>
+template <>
+inline bool
+is_a_helper <hsa_insn_atomic *>::test (hsa_insn_basic *p)
+{
+  return (p->m_opcode == BRIG_OPCODE_ATOMIC
+         || p->m_opcode == BRIG_OPCODE_ATOMICNORET);
+}
+
+/* HSA instruction for signal operations.  */
+
+class hsa_insn_signal : public hsa_insn_basic
+{
+public:
+  hsa_insn_signal (int nops, int opc, enum BrigAtomicOperation sop,
+                  BrigType16_t t, BrigMemoryOrder memorder,
+                  hsa_op_base *arg0 = NULL, hsa_op_base *arg1 = NULL,
+                  hsa_op_base *arg2 = NULL, hsa_op_base *arg3 = NULL);
+
+  /* Things like acquire/release/aligned.  */
+  enum BrigMemoryOrder m_memory_order;
+
+  /* The operation itself.  */
+  enum BrigAtomicOperation m_signalop;
+};
+
+/* Report whether or not P is a signal instruction.  */
+
+template <>
+template <>
+inline bool
+is_a_helper <hsa_insn_signal *>::test (hsa_insn_basic *p)
+{
+  return (p->m_opcode == BRIG_OPCODE_SIGNAL
+         || p->m_opcode == BRIG_OPCODE_SIGNALNORET);
+}
+
+/* HSA instruction to convert between flat addressing and segments.  */
+
+class hsa_insn_seg : public hsa_insn_basic
+{
+public:
+  hsa_insn_seg (int opc, BrigType16_t destt, BrigType16_t srct,
+               BrigSegment8_t seg, hsa_op_base *arg0, hsa_op_base *arg1);
+
+  /* Source type.  Depends on the source addressing/segment.  */
+  BrigType16_t m_src_type;
+  /* The segment we are converting from or to.  */
+  BrigSegment8_t m_segment;
+private:
+  /* Make the default constructor inaccessible.  */
+  hsa_insn_seg () : hsa_insn_basic (1, BRIG_OPCODE_STOF) {}
+};
+
+/* Report whether or not P is a segment conversion instruction.  */
+
+template <>
+template <>
+inline bool
+is_a_helper <hsa_insn_seg *>::test (hsa_insn_basic *p)
+{
+  return (p->m_opcode == BRIG_OPCODE_STOF
+         || p->m_opcode == BRIG_OPCODE_FTOS);
+}
+
+/* Class for internal functions for purpose of HSA emission.  */
+
+class hsa_internal_fn
+{
+public:
+  hsa_internal_fn (enum internal_fn fn, unsigned type_bit_size):
+    m_fn (fn), m_type_bit_size (type_bit_size), m_offset (0) {}
+
+  hsa_internal_fn (const hsa_internal_fn *f):
+    m_fn (f->m_fn), m_type_bit_size (f->m_type_bit_size),
+    m_offset (f->m_offset) {}
+
+  /* Return arity of the internal function.  */
+  unsigned get_arity ();
+
+  /* Return BRIG type of N-th argument, if -1 is passed, return value type
+     is received.  */
+  BrigType16_t get_argument_type (int n);
+
+  /* Return function name.  The memory must be released by a caller.  */
+  char *name ();
+
+  /* Internal function.  */
+  enum internal_fn m_fn;
+
+  /* Bit width of return type.  */
+  unsigned m_type_bit_size;
+
+  /* BRIG offset of declaration of the function.  */
+  BrigCodeOffset32_t m_offset;
+};
+
+/* HSA instruction for function call.  */
+
+class hsa_insn_call : public hsa_insn_basic
+{
+public:
+  hsa_insn_call (tree callee);
+  hsa_insn_call (hsa_internal_fn *fn);
+
+  /* Default destructor.  */
+  ~hsa_insn_call ();
+
+  /* Called function.  */
+  tree m_called_function;
+
+  /* Called internal function.  */
+  hsa_internal_fn *m_called_internal_fn;
+
+  /* Input formal arguments.  */
+  auto_vec <hsa_symbol *> m_input_args;
+
+  /* Input arguments store instructions.  */
+  auto_vec <hsa_insn_mem *> m_input_arg_insns;
+
+  /* Output argument, can be NULL for void functions.  */
+  hsa_symbol *m_output_arg;
+
+  /* Called function code reference.  */
+  hsa_op_code_ref m_func;
+
+  /* Code list for arguments of the function.  */
+  hsa_op_code_list *m_args_code_list;
+
+  /* Code list for result of the function.  */
+  hsa_op_code_list *m_result_code_list;
+private:
+  /* Make the default constructor inaccessible.  */
+  hsa_insn_call () : hsa_insn_basic (0, BRIG_OPCODE_CALL) {}
+};
+
+/* Report whether or not P is a call instruction.  */
+
+template <>
+template <>
+inline bool
+is_a_helper <hsa_insn_call *>::test (hsa_insn_basic *p)
+{
+  return (p->m_opcode == BRIG_OPCODE_CALL);
+}
+
+/* HSA call instruction block encapsulates definition of arguments,
+   result type, corresponding loads and a possible store.
+   Moreover, it contains a single call instruction.
+   Emission of the instruction will produce multiple
+   HSAIL instructions.  */
+
+class hsa_insn_arg_block : public hsa_insn_basic
+{
+public:
+  hsa_insn_arg_block (BrigKind brig_kind, hsa_insn_call * call);
+
+  /* Kind of argument block.  */
+  BrigKind m_kind;
+
+  /* Call instruction.  */
+  hsa_insn_call *m_call_insn;
+};
+
+/* Report whether or not P is a call block instruction.  */
+
+template <>
+template <>
+inline bool
+is_a_helper <hsa_insn_arg_block *>::test (hsa_insn_basic *p)
+{
+  return (p->m_opcode == HSA_OPCODE_ARG_BLOCK);
+}
+
+/* HSA comment instruction.  */
+
+class hsa_insn_comment: public hsa_insn_basic
+{
+public:
+  /* Constructor of class representing the comment in HSAIL.  */
+  hsa_insn_comment (const char *s);
+
+  /* Default destructor.  */
+  ~hsa_insn_comment ();
+
+  char *m_comment;
+};
+
+/* Report whether or not P is a call block instruction.  */
+
+template <>
+template <>
+inline bool
+is_a_helper <hsa_insn_comment *>::test (hsa_insn_basic *p)
+{
+  return (p->m_opcode == BRIG_KIND_DIRECTIVE_COMMENT);
+}
+
+/* HSA queue instruction.  */
+
+class hsa_insn_queue: public hsa_insn_basic
+{
+public:
+  hsa_insn_queue (int nops, int opcode, BrigSegment segment,
+                 BrigMemoryOrder memory_order,
+                 hsa_op_base *arg0 = NULL, hsa_op_base *arg1 = NULL,
+                 hsa_op_base *arg2 = NULL, hsa_op_base *arg3 = NULL);
+
+  /* Destructor.  */
+  ~hsa_insn_queue ();
+
+  /* Segment used to refer to the queue.  Must be global or flat.  */
+  BrigSegment m_segment;
+  /* Memory order used to specify synchronization.  */
+  BrigMemoryOrder m_memory_order;
+};
+
+/* Report whether or not P is a queue instruction.  */
+
+template <>
+template <>
+inline bool
+is_a_helper <hsa_insn_queue *>::test (hsa_insn_basic *p)
+{
+  return (p->m_opcode == BRIG_OPCODE_ADDQUEUEWRITEINDEX
+         || p->m_opcode == BRIG_OPCODE_CASQUEUEWRITEINDEX
+         || p->m_opcode == BRIG_OPCODE_LDQUEUEREADINDEX
+         || p->m_opcode == BRIG_OPCODE_LDQUEUEWRITEINDEX
+         || p->m_opcode == BRIG_OPCODE_STQUEUEREADINDEX
+         || p->m_opcode == BRIG_OPCODE_STQUEUEWRITEINDEX);
+}
+
+/* HSA source type instruction.  */
+
+class hsa_insn_srctype: public hsa_insn_basic
+{
+public:
+  hsa_insn_srctype (int nops, BrigOpcode opcode, BrigType16_t destt,
+                  BrigType16_t srct, hsa_op_base *arg0, hsa_op_base *arg1,
+                  hsa_op_base *arg2);
+
+  /* Source type.  */
+  BrigType16_t m_source_type;
+
+  /* Destructor.  */
+  ~hsa_insn_srctype ();
+};
+
+/* Report whether or not P is a source type instruction.  */
+
+template <>
+template <>
+inline bool
+is_a_helper <hsa_insn_srctype *>::test (hsa_insn_basic *p)
+{
+  return (p->m_opcode == BRIG_OPCODE_POPCOUNT
+         || p->m_opcode == BRIG_OPCODE_FIRSTBIT
+         || p->m_opcode == BRIG_OPCODE_LASTBIT);
+}
+
+/* HSA packed instruction.  */
+
+class hsa_insn_packed : public hsa_insn_srctype
+{
+public:
+  hsa_insn_packed (int nops, BrigOpcode opcode, BrigType16_t destt,
+                  BrigType16_t srct, hsa_op_base *arg0, hsa_op_base *arg1,
+                  hsa_op_base *arg2);
+
+  /* Operand list for an operand of the instruction.  */
+  hsa_op_operand_list *m_operand_list;
+
+  /* Destructor.  */
+  ~hsa_insn_packed ();
+};
+
+/* Report whether or not P is a combine instruction.  */
+
+template <>
+template <>
+inline bool
+is_a_helper <hsa_insn_packed *>::test (hsa_insn_basic *p)
+{
+  return (p->m_opcode == BRIG_OPCODE_COMBINE
+         || p->m_opcode == BRIG_OPCODE_EXPAND);
+}
+
+/* HSA convert instruction.  */
+
+class hsa_insn_cvt: public hsa_insn_basic
+{
+public:
+  hsa_insn_cvt (hsa_op_with_type *dest, hsa_op_with_type *src);
+};
+
+/* Report whether or not P is a convert instruction.  */
+
+template <>
+template <>
+inline bool
+is_a_helper <hsa_insn_cvt *>::test (hsa_insn_basic *p)
+{
+  return (p->m_opcode == BRIG_OPCODE_CVT);
+}
+
+/* HSA alloca instruction.  */
+
+class hsa_insn_alloca: public hsa_insn_basic
+{
+public:
+  hsa_insn_alloca (hsa_op_with_type *dest, hsa_op_with_type *size,
+                  unsigned alignment = 0);
+
+  /* Required alignment of the allocation.  */
+  BrigAlignment8_t m_align;
+};
+
+/* Report whether or not P is an alloca instruction.  */
+
+template <>
+template <>
+inline bool
+is_a_helper <hsa_insn_alloca *>::test (hsa_insn_basic *p)
+{
+  return (p->m_opcode == BRIG_OPCODE_ALLOCA);
+}
+
+/* Basic block of HSA instructions.  */
+
+class hsa_bb
+{
+public:
+  hsa_bb (basic_block cfg_bb);
+  hsa_bb (basic_block cfg_bb, int idx);
+  ~hsa_bb ();
+
+  /* Append an instruction INSN into the basic block.  */
+  void append_insn (hsa_insn_basic *insn);
+
+  /* Add a PHI instruction.  */
+  void append_phi (hsa_insn_phi *phi);
+
+  /* The real CFG BB that this HBB belongs to.  */
+  basic_block m_bb;
+
+  /* The operand that refers to the label to this BB.  */
+  hsa_op_code_ref m_label_ref;
+
+  /* The first and last instruction.  */
+  hsa_insn_basic *m_first_insn, *m_last_insn;
+  /* The first and last phi node.  */
+  hsa_insn_phi *m_first_phi, *m_last_phi;
+
+  /* Just a number to construct names from.  */
+  int m_index;
+
+  bitmap m_liveout, m_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
+   flow basic_block BB.  */
+
+static inline hsa_bb *
+hsa_bb_for_bb (basic_block bb)
+{
+  return (struct hsa_bb *) bb->aux;
+}
+
+/* Class for hashing local hsa_symbols.  */
+
+struct hsa_noop_symbol_hasher : nofree_ptr_hash <hsa_symbol>
+{
+  static inline hashval_t hash (const value_type);
+  static inline bool equal (const value_type, const compare_type);
+};
+
+/* Hash hsa_symbol.  */
+
+inline hashval_t
+hsa_noop_symbol_hasher::hash (const value_type item)
+{
+  return DECL_UID (item->m_decl);
+}
+
+/* Return true if the DECL_UIDs of decls both symbols refer to are equal.  */
+
+inline bool
+hsa_noop_symbol_hasher::equal (const value_type a, const compare_type b)
+{
+  return (DECL_UID (a->m_decl) == DECL_UID (b->m_decl));
+}
+
+/* Structure that encapsulates intermediate representation of a HSA
+   function.  */
+
+class hsa_function_representation
+{
+public:
+  hsa_function_representation (tree fdecl, bool kernel_p,
+                              unsigned ssa_names_count,
+                              bool modified_cfg = false);
+  hsa_function_representation (hsa_internal_fn *fn);
+  ~hsa_function_representation ();
+
+  /* Builds a shadow register that is utilized to a kernel dispatch.  */
+  hsa_op_reg *get_shadow_reg ();
+
+  /* Return true if we are in a function that has kernel dispatch
+     shadow register.  */
+  bool has_shadow_reg_p ();
+
+  /* The entry/exit blocks don't contain incoming code,
+     but the HSA generator might use them to put code into,
+     so we need hsa_bb instances of them.  */
+  void init_extra_bbs ();
+
+  /* Update CFG dominators if m_modified_cfg flag is set.  */
+  void update_dominance ();
+
+  /* Return linkage of the representation.  */
+  BrigLinkage8_t get_linkage ();
+
+  /* Create a private symbol of requested TYPE.  */
+  hsa_symbol *create_hsa_temporary (BrigType16_t type);
+
+  /* Lookup or create a HSA pseudo register for a given gimple SSA name.  */
+  hsa_op_reg *reg_for_gimple_ssa (tree ssa);
+
+  /* Name of the function.  */
+  char *m_name;
+
+  /* Number of allocated register structures.  */
+  int m_reg_count;
+
+  /* Input arguments.  */
+  vec <hsa_symbol *> m_input_args;
+
+  /* Output argument or NULL if there is none.  */
+  hsa_symbol *m_output_arg;
+
+  /* Hash table of local variable symbols.  */
+  hash_table <hsa_noop_symbol_hasher> *m_local_symbols;
+
+  /* Hash map for string constants.  */
+  hash_map <tree, hsa_symbol *> m_string_constants_map;
+
+  /* Vector of pointers to spill symbols.  */
+  vec <struct hsa_symbol *> m_spill_symbols;
+
+  /* Vector of pointers to global variables and transformed string constants
+     that are used by the function.  */
+  vec <struct hsa_symbol *> m_global_symbols;
+
+  /* Private function artificial variables.  */
+  vec <struct hsa_symbol *> m_private_variables;
+
+  /* Vector of called function declarations.  */
+  vec <tree> m_called_functions;
+
+  /* Vector of used internal functions.  */
+  vec <hsa_internal_fn *> m_called_internal_fns;
+
+  /* Number of HBB BBs.  */
+  int m_hbb_count;
+
+  /* Whether or not we could check and enforce SSA properties.  */
+  bool m_in_ssa;
+
+  /* True if the function is kernel function.  */
+  bool m_kern_p;
+
+  /* True if the function representation is a declaration.  */
+  bool m_declaration_p;
+
+  /* Function declaration tree.  */
+  tree m_decl;
+
+  /* Internal function info is used for declarations of internal functions.  */
+  hsa_internal_fn *m_internal_fn;
+
+  /* Runtime shadow register.  */
+  hsa_op_reg *m_shadow_reg;
+
+  /* Number of kernel dispatched which take place in the function.  */
+  unsigned m_kernel_dispatch_count;
+
+  /* If the function representation contains a kernel dispatch,
+     OMP data size is necessary memory that is used for copying before
+     a kernel dispatch.  */
+  unsigned m_maximum_omp_data_size;
+
+  /* Return true if there's an HSA-specific warning already seen.  */
+  bool m_seen_error;
+
+  /* Counter for temporary symbols created in the function representation.  */
+  unsigned m_temp_symbol_count;
+
+  /* SSA names mapping.  */
+  vec <hsa_op_reg *> m_ssa_map;
+
+  /* Flag whether a function needs update of dominators before RA.  */
+  bool m_modified_cfg;
+};
+
+enum hsa_function_kind
+{
+  HSA_NONE,
+  HSA_KERNEL,
+  HSA_FUNCTION
+};
+
+struct hsa_function_summary
+{
+  /* Default constructor.  */
+  hsa_function_summary ();
+
+  /* Kind of GPU/host function.  */
+  hsa_function_kind m_kind;
+
+  /* Pointer to a cgraph node which is a HSA implementation of the function.
+     In case of the function is a HSA function, the bound function points
+     to the host function.  */
+  cgraph_node *m_bound_function;
+
+  /* Identifies if the function is an HSA function or a host function.  */
+  bool m_gpu_implementation_p;
+
+  /* True if the function is a gridified kernel.  */
+  bool m_gridified_kernel_p;
+};
+
+inline
+hsa_function_summary::hsa_function_summary (): m_kind (HSA_NONE),
+  m_bound_function (NULL), m_gpu_implementation_p (false)
+{
+}
+
+/* Function summary for HSA functions.  */
+class hsa_summary_t: public function_summary <hsa_function_summary *>
+{
+public:
+  hsa_summary_t (symbol_table *table):
+    function_summary<hsa_function_summary *> (table) { }
+
+  /* Couple GPU and HOST as gpu-specific and host-specific implementation of
+     the same function.  KIND determines whether GPU is a host-invokable kernel
+     or gpu-callable function and GRIDIFIED_KERNEL_P is set if the function was
+     gridified in OMP.  */
+
+  void link_functions (cgraph_node *gpu, cgraph_node *host,
+                      hsa_function_kind kind, bool gridified_kernel_p);
+
+private:
+  void process_gpu_implementation_attributes (tree gdecl);
+};
+
+/* OMP simple builtin describes behavior that should be done for
+   the routine.  */
+class omp_simple_builtin
+{
+public:
+  omp_simple_builtin (const char *name, const char *warning_message,
+              bool sorry, hsa_op_immed *return_value = NULL):
+    m_name (name), m_warning_message (warning_message), m_sorry (sorry),
+    m_return_value (return_value)
+  {}
+
+  /* Generate HSAIL instructions for the builtin or produce warning message.  */
+  void generate (gimple *stmt, hsa_bb *hbb);
+
+  /* Name of function.  */
+  const char *m_name;
+
+  /* Warning message.  */
+  const char *m_warning_message;
+
+  /* Flag if we should sorry after the warning message is printed.  */
+  bool m_sorry;
+
+  /* Return value of the function.  */
+  hsa_op_immed *m_return_value;
+
+  /* Emission function.  */
+  void (*m_emit_func) (gimple *stmt, hsa_bb *);
+};
+
+/* Class for hashing hsa_internal_fn.  */
+
+struct hsa_internal_fn_hasher: free_ptr_hash <hsa_internal_fn>
+{
+  static inline hashval_t hash (const value_type);
+  static inline bool equal (const value_type, const compare_type);
+};
+
+/* Hash hsa_symbol.  */
+
+inline hashval_t
+hsa_internal_fn_hasher::hash (const value_type item)
+{
+  return item->m_fn;
+}
+
+/* Return true if the DECL_UIDs of decls both symbols refer to  are equal.  */
+
+inline bool
+hsa_internal_fn_hasher::equal (const value_type a, const compare_type b)
+{
+  return a->m_fn == b->m_fn && a->m_type_bit_size == b->m_type_bit_size;
+}
+
+/* in hsa-common.c */
+extern struct hsa_function_representation *hsa_cfun;
+extern hash_map <tree, vec <const char *> *> *hsa_decl_kernel_dependencies;
+extern hsa_summary_t *hsa_summaries;
+extern hsa_symbol *hsa_num_threads;
+extern unsigned hsa_kernel_calls_counter;
+extern hash_set <tree> *hsa_failed_functions;
+extern hash_table <hsa_noop_symbol_hasher> *hsa_global_variable_symbols;
+
+bool hsa_callable_function_p (tree fndecl);
+void hsa_init_compilation_unit_data (void);
+void hsa_deinit_compilation_unit_data (void);
+bool hsa_machine_large_p (void);
+bool hsa_full_profile_p (void);
+bool hsa_opcode_floating_bit_insn_p (BrigOpcode16_t);
+unsigned hsa_type_bit_size (BrigType16_t t);
+BrigType16_t hsa_bittype_for_bitsize (unsigned bitsize);
+BrigType16_t hsa_uint_for_bitsize (unsigned bitsize);
+BrigType16_t hsa_float_for_bitsize (unsigned bitsize);
+BrigType16_t hsa_bittype_for_type (BrigType16_t t);
+BrigType16_t hsa_unsigned_type_for_type (BrigType16_t t);
+bool hsa_type_packed_p (BrigType16_t type);
+bool hsa_type_float_p (BrigType16_t type);
+bool hsa_type_integer_p (BrigType16_t type);
+bool hsa_btype_p (BrigType16_t type);
+BrigAlignment8_t hsa_alignment_encoding (unsigned n);
+BrigAlignment8_t hsa_natural_alignment (BrigType16_t type);
+BrigAlignment8_t hsa_object_alignment (tree t);
+unsigned hsa_byte_alignment (BrigAlignment8_t alignment);
+void hsa_destroy_operand (hsa_op_base *op);
+void hsa_destroy_insn (hsa_insn_basic *insn);
+void hsa_add_kern_decl_mapping (tree decl, char *name, unsigned, bool);
+unsigned hsa_get_number_decl_kernel_mappings (void);
+tree hsa_get_decl_kernel_mapping_decl (unsigned i);
+char *hsa_get_decl_kernel_mapping_name (unsigned i);
+unsigned hsa_get_decl_kernel_mapping_omp_size (unsigned i);
+bool hsa_get_decl_kernel_mapping_gridified (unsigned i);
+void hsa_free_decl_kernel_mapping (void);
+tree *hsa_get_ctor_statements (void);
+tree *hsa_get_dtor_statements (void);
+tree *hsa_get_kernel_dispatch_type (void);
+void hsa_add_kernel_dependency (tree caller, const char *called_function);
+void hsa_sanitize_name (char *p);
+char *hsa_brig_function_name (const char *p);
+const char *hsa_get_declaration_name (tree decl);
+void hsa_register_kernel (cgraph_node *host);
+void hsa_register_kernel (cgraph_node *gpu, cgraph_node *host);
+bool hsa_seen_error (void);
+void hsa_fail_cfun (void);
+
+/* In hsa-gen.c.  */
+void hsa_build_append_simple_mov (hsa_op_reg *, hsa_op_base *, hsa_bb *);
+hsa_symbol *hsa_get_spill_symbol (BrigType16_t);
+hsa_symbol *hsa_get_string_cst_symbol (BrigType16_t);
+hsa_op_reg *hsa_spill_in (hsa_insn_basic *, hsa_op_reg *, hsa_op_reg **);
+hsa_op_reg *hsa_spill_out (hsa_insn_basic *, hsa_op_reg *, hsa_op_reg **);
+hsa_bb *hsa_init_new_bb (basic_block);
+hsa_function_representation *hsa_generate_function_declaration (tree decl);
+hsa_function_representation *hsa_generate_internal_fn_decl (hsa_internal_fn *);
+tree hsa_get_host_function (tree decl);
+
+/* In hsa-regalloc.c.  */
+void hsa_regalloc (void);
+
+/* In hsa-brig.c.  */
+extern hash_table <hsa_internal_fn_hasher> *hsa_emitted_internal_decls;
+void hsa_brig_emit_function (void);
+void hsa_output_brig (void);
+unsigned hsa_get_imm_brig_type_len (BrigType16_t type);
+void hsa_brig_emit_omp_symbols (void);
+
+/*  In hsa-dump.c.  */
+const char *hsa_seg_name (BrigSegment8_t);
+void dump_hsa_insn (FILE *f, hsa_insn_basic *insn);
+void dump_hsa_bb (FILE *, hsa_bb *);
+void dump_hsa_cfun (FILE *);
+DEBUG_FUNCTION void debug_hsa_operand (hsa_op_base *opc);
+DEBUG_FUNCTION void debug_hsa_insn (hsa_insn_basic *insn);
+
+union hsa_bytes
+{
+  uint8_t b8;
+  uint16_t b16;
+  uint32_t b32;
+  uint64_t b64;
+};
+
+/* Return true if a function DECL is an HSA implementation.  */
+
+static inline bool
+hsa_gpu_implementation_p (tree decl)
+{
+  if (hsa_summaries == NULL)
+    return false;
+
+  hsa_function_summary *s = hsa_summaries->get (cgraph_node::get_create (decl));
+
+  return s->m_gpu_implementation_p;
+}
+
+#endif /* HSA_H */
index 1cd128ea3b42697036687dfd7b249b4033eef31f..e2ef58693c9601961f4f2a46f74a7fc69e234a31 100644 (file)
@@ -33,7 +33,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "cgraph.h"
 #include "print-tree.h"
 #include "symbol-summary.h"
-#include "hsa.h"
+#include "hsa-common.h"
 
 /* Return textual name of TYPE.  */
 
index 632561d5e45df6d2456c57feb1bb38820f20659e..7721fcc933415f1ba430341b5d693ebe0d29b252 100644 (file)
@@ -49,7 +49,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "cgraph.h"
 #include "print-tree.h"
 #include "symbol-summary.h"
-#include "hsa.h"
+#include "hsa-common.h"
 #include "cfghooks.h"
 #include "tree-cfg.h"
 #include "cfgloop.h"
index 5f2ac13c8239696421db309097583f04e2477021..4d9441c91d4efd51783de08824dbc3ebe2d3cb5d 100644 (file)
@@ -35,7 +35,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "print-tree.h"
 #include "cfghooks.h"
 #include "symbol-summary.h"
-#include "hsa.h"
+#include "hsa-common.h"
 
 
 /* Process a PHI node PHI of basic block BB as a part of naive out-f-ssa.  */
diff --git a/gcc/hsa.c b/gcc/hsa.c
deleted file mode 100644 (file)
index 2035ce4..0000000
--- a/gcc/hsa.c
+++ /dev/null
@@ -1,994 +0,0 @@
-/* Implementation of commonly needed HSAIL related functions and methods.
-   Copyright (C) 2013-2017 Free Software Foundation, Inc.
-   Contributed by Martin Jambor <mjambor@suse.cz> and
-   Martin Liska <mliska@suse.cz>.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3.  If not see
-<http://www.gnu.org/licenses/>.  */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "is-a.h"
-#include "hash-set.h"
-#include "hash-map.h"
-#include "vec.h"
-#include "tree.h"
-#include "dumpfile.h"
-#include "gimple-pretty-print.h"
-#include "diagnostic-core.h"
-#include "alloc-pool.h"
-#include "cgraph.h"
-#include "print-tree.h"
-#include "stringpool.h"
-#include "symbol-summary.h"
-#include "hsa.h"
-#include "internal-fn.h"
-#include "ctype.h"
-#include "builtins.h"
-
-/* Structure containing intermediate HSA representation of the generated
-   function.  */
-class hsa_function_representation *hsa_cfun;
-
-/* Element of the mapping vector between a host decl and an HSA kernel.  */
-
-struct GTY(()) hsa_decl_kernel_map_element
-{
-  /* The decl of the host function.  */
-  tree decl;
-  /* Name of the HSA kernel in BRIG.  */
-  char * GTY((skip)) name;
-  /* Size of OMP data, if the kernel contains a kernel dispatch.  */
-  unsigned omp_data_size;
-  /* True if the function is gridified kernel.  */
-  bool gridified_kernel_p;
-};
-
-/* Mapping between decls and corresponding HSA kernels in this compilation
-   unit.  */
-
-static GTY (()) vec<hsa_decl_kernel_map_element, va_gc>
-  *hsa_decl_kernel_mapping;
-
-/* Mapping between decls and corresponding HSA kernels
-   called by the function.  */
-hash_map <tree, vec <const char *> *> *hsa_decl_kernel_dependencies;
-
-/* Hash function to lookup a symbol for a decl.  */
-hash_table <hsa_noop_symbol_hasher> *hsa_global_variable_symbols;
-
-/* HSA summaries.  */
-hsa_summary_t *hsa_summaries = NULL;
-
-/* HSA number of threads.  */
-hsa_symbol *hsa_num_threads = NULL;
-
-/* HSA function that cannot be expanded to HSAIL.  */
-hash_set <tree> *hsa_failed_functions = NULL;
-
-/* True if compilation unit-wide data are already allocated and initialized.  */
-static bool compilation_unit_data_initialized;
-
-/* Return true if FNDECL represents an HSA-callable function.  */
-
-bool
-hsa_callable_function_p (tree fndecl)
-{
-  return (lookup_attribute ("omp declare target", DECL_ATTRIBUTES (fndecl))
-         && !lookup_attribute ("oacc function", DECL_ATTRIBUTES (fndecl)));
-}
-
-/* Allocate HSA structures that are are used when dealing with different
-   functions.  */
-
-void
-hsa_init_compilation_unit_data (void)
-{
-  if (compilation_unit_data_initialized)
-    return;
-
-  compilation_unit_data_initialized = true;
-
-  hsa_global_variable_symbols = new hash_table <hsa_noop_symbol_hasher> (8);
-  hsa_failed_functions = new hash_set <tree> ();
-  hsa_emitted_internal_decls = new hash_table <hsa_internal_fn_hasher> (2);
-}
-
-/* Free data structures that are used when dealing with different
-   functions.  */
-
-void
-hsa_deinit_compilation_unit_data (void)
-{
-  gcc_assert (compilation_unit_data_initialized);
-
-  delete hsa_failed_functions;
-  delete hsa_emitted_internal_decls;
-
-  for (hash_table <hsa_noop_symbol_hasher>::iterator it
-       = hsa_global_variable_symbols->begin ();
-       it != hsa_global_variable_symbols->end ();
-       ++it)
-    {
-      hsa_symbol *sym = *it;
-      delete sym;
-    }
-
-  delete hsa_global_variable_symbols;
-
-  if (hsa_num_threads)
-    {
-      delete hsa_num_threads;
-      hsa_num_threads = NULL;
-    }
-
-  compilation_unit_data_initialized = false;
-}
-
-/* Return true if we are generating large HSA machine model.  */
-
-bool
-hsa_machine_large_p (void)
-{
-  /* FIXME: I suppose this is technically wrong but should work for me now.  */
-  return (GET_MODE_BITSIZE (Pmode) == 64);
-}
-
-/* Return the HSA profile we are using.  */
-
-bool
-hsa_full_profile_p (void)
-{
-  return true;
-}
-
-/* Return true if a register in operand number OPNUM of instruction
-   is an output.  False if it is an input.  */
-
-bool
-hsa_insn_basic::op_output_p (unsigned opnum)
-{
-  switch (m_opcode)
-    {
-    case HSA_OPCODE_PHI:
-    case BRIG_OPCODE_CBR:
-    case BRIG_OPCODE_SBR:
-    case BRIG_OPCODE_ST:
-    case BRIG_OPCODE_SIGNALNORET:
-    case BRIG_OPCODE_DEBUGTRAP:
-      /* FIXME: There are probably missing cases here, double check.  */
-      return false;
-    case BRIG_OPCODE_EXPAND:
-      /* Example: expand_v4_b32_b128 (dest0, dest1, dest2, dest3), src0.  */
-      return opnum < operand_count () - 1;
-    default:
-     return opnum == 0;
-    }
-}
-
-/* Return true if OPCODE is an floating-point bit instruction opcode.  */
-
-bool
-hsa_opcode_floating_bit_insn_p (BrigOpcode16_t opcode)
-{
-  switch (opcode)
-    {
-    case BRIG_OPCODE_NEG:
-    case BRIG_OPCODE_ABS:
-    case BRIG_OPCODE_CLASS:
-    case BRIG_OPCODE_COPYSIGN:
-      return true;
-    default:
-      return false;
-    }
-}
-
-/* Return the number of destination operands for this INSN.  */
-
-unsigned
-hsa_insn_basic::input_count ()
-{
-  switch (m_opcode)
-    {
-      default:
-       return 1;
-
-      case BRIG_OPCODE_NOP:
-       return 0;
-
-      case BRIG_OPCODE_EXPAND:
-       return 2;
-
-      case BRIG_OPCODE_LD:
-       /* ld_v[234] not yet handled.  */
-       return 1;
-
-      case BRIG_OPCODE_ST:
-       return 0;
-
-      case BRIG_OPCODE_ATOMICNORET:
-       return 0;
-
-      case BRIG_OPCODE_SIGNAL:
-       return 1;
-
-      case BRIG_OPCODE_SIGNALNORET:
-       return 0;
-
-      case BRIG_OPCODE_MEMFENCE:
-       return 0;
-
-      case BRIG_OPCODE_RDIMAGE:
-      case BRIG_OPCODE_LDIMAGE:
-      case BRIG_OPCODE_STIMAGE:
-      case BRIG_OPCODE_QUERYIMAGE:
-      case BRIG_OPCODE_QUERYSAMPLER:
-       sorry ("HSA image ops not handled");
-       return 0;
-
-      case BRIG_OPCODE_CBR:
-      case BRIG_OPCODE_BR:
-       return 0;
-
-      case BRIG_OPCODE_SBR:
-       return 0; /* ??? */
-
-      case BRIG_OPCODE_WAVEBARRIER:
-       return 0; /* ??? */
-
-      case BRIG_OPCODE_BARRIER:
-      case BRIG_OPCODE_ARRIVEFBAR:
-      case BRIG_OPCODE_INITFBAR:
-      case BRIG_OPCODE_JOINFBAR:
-      case BRIG_OPCODE_LEAVEFBAR:
-      case BRIG_OPCODE_RELEASEFBAR:
-      case BRIG_OPCODE_WAITFBAR:
-       return 0;
-
-      case BRIG_OPCODE_LDF:
-       return 1;
-
-      case BRIG_OPCODE_ACTIVELANECOUNT:
-      case BRIG_OPCODE_ACTIVELANEID:
-      case BRIG_OPCODE_ACTIVELANEMASK:
-      case BRIG_OPCODE_ACTIVELANEPERMUTE:
-       return 1; /* ??? */
-
-      case BRIG_OPCODE_CALL:
-      case BRIG_OPCODE_SCALL:
-      case BRIG_OPCODE_ICALL:
-       return 0;
-
-      case BRIG_OPCODE_RET:
-       return 0;
-
-      case BRIG_OPCODE_ALLOCA:
-       return 1;
-
-      case BRIG_OPCODE_CLEARDETECTEXCEPT:
-       return 0;
-
-      case BRIG_OPCODE_SETDETECTEXCEPT:
-       return 0;
-
-      case BRIG_OPCODE_PACKETCOMPLETIONSIG:
-      case BRIG_OPCODE_PACKETID:
-      case BRIG_OPCODE_CASQUEUEWRITEINDEX:
-      case BRIG_OPCODE_LDQUEUEREADINDEX:
-      case BRIG_OPCODE_LDQUEUEWRITEINDEX:
-      case BRIG_OPCODE_STQUEUEREADINDEX:
-      case BRIG_OPCODE_STQUEUEWRITEINDEX:
-       return 1; /* ??? */
-
-      case BRIG_OPCODE_ADDQUEUEWRITEINDEX:
-       return 1;
-
-      case BRIG_OPCODE_DEBUGTRAP:
-       return 0;
-
-      case BRIG_OPCODE_GROUPBASEPTR:
-      case BRIG_OPCODE_KERNARGBASEPTR:
-       return 1; /* ??? */
-
-      case HSA_OPCODE_ARG_BLOCK:
-       return 0;
-
-      case BRIG_KIND_DIRECTIVE_COMMENT:
-       return 0;
-    }
-}
-
-/* Return the number of source operands for this INSN.  */
-
-unsigned
-hsa_insn_basic::num_used_ops ()
-{
-  gcc_checking_assert (input_count () <= operand_count ());
-
-  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 < m_align)
-    {
-      fprintf (dump_file, "Decreasing alignment to %u in instruction ", value);
-      dump_hsa_insn (dump_file, this);
-    }
-  m_align = value;
-}
-
-/* Return size of HSA type T in bits.  */
-
-unsigned
-hsa_type_bit_size (BrigType16_t t)
-{
-  switch (t)
-    {
-    case BRIG_TYPE_B1:
-      return 1;
-
-    case BRIG_TYPE_U8:
-    case BRIG_TYPE_S8:
-    case BRIG_TYPE_B8:
-      return 8;
-
-    case BRIG_TYPE_U16:
-    case BRIG_TYPE_S16:
-    case BRIG_TYPE_B16:
-    case BRIG_TYPE_F16:
-      return 16;
-
-    case BRIG_TYPE_U32:
-    case BRIG_TYPE_S32:
-    case BRIG_TYPE_B32:
-    case BRIG_TYPE_F32:
-    case BRIG_TYPE_U8X4:
-    case BRIG_TYPE_U16X2:
-    case BRIG_TYPE_S8X4:
-    case BRIG_TYPE_S16X2:
-    case BRIG_TYPE_F16X2:
-      return 32;
-
-    case BRIG_TYPE_U64:
-    case BRIG_TYPE_S64:
-    case BRIG_TYPE_F64:
-    case BRIG_TYPE_B64:
-    case BRIG_TYPE_U8X8:
-    case BRIG_TYPE_U16X4:
-    case BRIG_TYPE_U32X2:
-    case BRIG_TYPE_S8X8:
-    case BRIG_TYPE_S16X4:
-    case BRIG_TYPE_S32X2:
-    case BRIG_TYPE_F16X4:
-    case BRIG_TYPE_F32X2:
-
-      return 64;
-
-    case BRIG_TYPE_B128:
-    case BRIG_TYPE_U8X16:
-    case BRIG_TYPE_U16X8:
-    case BRIG_TYPE_U32X4:
-    case BRIG_TYPE_U64X2:
-    case BRIG_TYPE_S8X16:
-    case BRIG_TYPE_S16X8:
-    case BRIG_TYPE_S32X4:
-    case BRIG_TYPE_S64X2:
-    case BRIG_TYPE_F16X8:
-    case BRIG_TYPE_F32X4:
-    case BRIG_TYPE_F64X2:
-      return 128;
-
-    default:
-      gcc_assert (hsa_seen_error ());
-      return t;
-    }
-}
-
-/* Return BRIG bit-type with BITSIZE length.  */
-
-BrigType16_t
-hsa_bittype_for_bitsize (unsigned bitsize)
-{
-  switch (bitsize)
-    {
-    case 1:
-      return BRIG_TYPE_B1;
-    case 8:
-      return BRIG_TYPE_B8;
-    case 16:
-      return BRIG_TYPE_B16;
-    case 32:
-      return BRIG_TYPE_B32;
-    case 64:
-      return BRIG_TYPE_B64;
-    case 128:
-      return BRIG_TYPE_B128;
-    default:
-      gcc_unreachable ();
-    }
-}
-
-/* Return BRIG unsigned int type with BITSIZE length.  */
-
-BrigType16_t
-hsa_uint_for_bitsize (unsigned bitsize)
-{
-  switch (bitsize)
-    {
-    case 8:
-      return BRIG_TYPE_U8;
-    case 16:
-      return BRIG_TYPE_U16;
-    case 32:
-      return BRIG_TYPE_U32;
-    case 64:
-      return BRIG_TYPE_U64;
-    default:
-      gcc_unreachable ();
-    }
-}
-
-/* Return BRIG float type with BITSIZE length.  */
-
-BrigType16_t
-hsa_float_for_bitsize (unsigned bitsize)
-{
-  switch (bitsize)
-    {
-    case 16:
-      return BRIG_TYPE_F16;
-    case 32:
-      return BRIG_TYPE_F32;
-    case 64:
-      return BRIG_TYPE_F64;
-    default:
-      gcc_unreachable ();
-    }
-}
-
-/* Return HSA bit-type with the same size as the type T.  */
-
-BrigType16_t
-hsa_bittype_for_type (BrigType16_t t)
-{
-  return hsa_bittype_for_bitsize (hsa_type_bit_size (t));
-}
-
-/* Return HSA unsigned integer type with the same size as the type T.  */
-
-BrigType16_t
-hsa_unsigned_type_for_type (BrigType16_t t)
-{
-  return hsa_uint_for_bitsize (hsa_type_bit_size (t));
-}
-
-/* Return true if TYPE is a packed HSA type.  */
-
-bool
-hsa_type_packed_p (BrigType16_t type)
-{
-  return (type & BRIG_TYPE_PACK_MASK) != BRIG_TYPE_PACK_NONE;
-}
-
-/* Return true if and only if TYPE is a floating point number type.  */
-
-bool
-hsa_type_float_p (BrigType16_t type)
-{
-  switch (type & BRIG_TYPE_BASE_MASK)
-    {
-    case BRIG_TYPE_F16:
-    case BRIG_TYPE_F32:
-    case BRIG_TYPE_F64:
-      return true;
-    default:
-      return false;
-    }
-}
-
-/* Return true if and only if TYPE is an integer number type.  */
-
-bool
-hsa_type_integer_p (BrigType16_t type)
-{
-  switch (type & BRIG_TYPE_BASE_MASK)
-    {
-    case BRIG_TYPE_U8:
-    case BRIG_TYPE_U16:
-    case BRIG_TYPE_U32:
-    case BRIG_TYPE_U64:
-    case BRIG_TYPE_S8:
-    case BRIG_TYPE_S16:
-    case BRIG_TYPE_S32:
-    case BRIG_TYPE_S64:
-      return true;
-    default:
-      return false;
-    }
-}
-
-/* Return true if and only if TYPE is an bit-type.  */
-
-bool
-hsa_btype_p (BrigType16_t type)
-{
-  switch (type & BRIG_TYPE_BASE_MASK)
-    {
-    case BRIG_TYPE_B8:
-    case BRIG_TYPE_B16:
-    case BRIG_TYPE_B32:
-    case BRIG_TYPE_B64:
-    case BRIG_TYPE_B128:
-      return true;
-    default:
-      return false;
-    }
-}
-
-
-/* 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 HSA alignment encoding alignment of T got
-   by get_object_alignment.  */
-
-BrigAlignment8_t
-hsa_object_alignment (tree t)
-{
-  return hsa_alignment_encoding (get_object_alignment (t));
-}
-
-/* Return byte alignment for given BrigAlignment8_t value.  */
-
-unsigned
-hsa_byte_alignment (BrigAlignment8_t alignment)
-{
-  gcc_assert (alignment != BRIG_ALIGNMENT_NONE);
-
-  return 1 << (alignment - 1);
-}
-
-/* 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 of a HSA instruction.  */
-
-void
-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_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))
-    mem->~hsa_insn_mem ();
-  else if (hsa_insn_atomic *atomic = dyn_cast <hsa_insn_atomic *> (insn))
-    atomic->~hsa_insn_atomic ();
-  else if (hsa_insn_seg *seg = dyn_cast <hsa_insn_seg *> (insn))
-    seg->~hsa_insn_seg ();
-  else if (hsa_insn_call *call = dyn_cast <hsa_insn_call *> (insn))
-    call->~hsa_insn_call ();
-  else if (hsa_insn_arg_block *block = dyn_cast <hsa_insn_arg_block *> (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
-    insn->~hsa_insn_basic ();
-}
-
-/* Call the correct destructor of a HSA operand.  */
-
-void
-hsa_destroy_operand (hsa_op_base *op)
-{
-  if (hsa_op_code_list *list = dyn_cast <hsa_op_code_list *> (op))
-    list->~hsa_op_code_list ();
-  else if (hsa_op_operand_list *list = dyn_cast <hsa_op_operand_list *> (op))
-    list->~hsa_op_operand_list ();
-  else if (hsa_op_reg *reg = dyn_cast <hsa_op_reg *> (op))
-    reg->~hsa_op_reg ();
-  else if (hsa_op_immed *immed = dyn_cast <hsa_op_immed *> (op))
-    immed->~hsa_op_immed ();
-  else
-    op->~hsa_op_base ();
-}
-
-/* Create a mapping between the original function DECL and kernel name NAME.  */
-
-void
-hsa_add_kern_decl_mapping (tree decl, char *name, unsigned omp_data_size,
-                          bool gridified_kernel_p)
-{
-  hsa_decl_kernel_map_element dkm;
-  dkm.decl = decl;
-  dkm.name = name;
-  dkm.omp_data_size = omp_data_size;
-  dkm.gridified_kernel_p = gridified_kernel_p;
-  vec_safe_push (hsa_decl_kernel_mapping, dkm);
-}
-
-/* Return the number of kernel decl name mappings.  */
-
-unsigned
-hsa_get_number_decl_kernel_mappings (void)
-{
-  return vec_safe_length (hsa_decl_kernel_mapping);
-}
-
-/* Return the decl in the Ith kernel decl name mapping.  */
-
-tree
-hsa_get_decl_kernel_mapping_decl (unsigned i)
-{
-  return (*hsa_decl_kernel_mapping)[i].decl;
-}
-
-/* Return the name in the Ith kernel decl name mapping.  */
-
-char *
-hsa_get_decl_kernel_mapping_name (unsigned i)
-{
-  return (*hsa_decl_kernel_mapping)[i].name;
-}
-
-/* Return maximum OMP size for kernel decl name mapping.  */
-
-unsigned
-hsa_get_decl_kernel_mapping_omp_size (unsigned i)
-{
-  return (*hsa_decl_kernel_mapping)[i].omp_data_size;
-}
-
-/* Return if the function is gridified kernel in decl name mapping.  */
-
-bool
-hsa_get_decl_kernel_mapping_gridified (unsigned i)
-{
-  return (*hsa_decl_kernel_mapping)[i].gridified_kernel_p;
-}
-
-/* Free the mapping between original decls and kernel names.  */
-
-void
-hsa_free_decl_kernel_mapping (void)
-{
-  if (hsa_decl_kernel_mapping == NULL)
-    return;
-
-  for (unsigned i = 0; i < hsa_decl_kernel_mapping->length (); ++i)
-    free ((*hsa_decl_kernel_mapping)[i].name);
-  ggc_free (hsa_decl_kernel_mapping);
-}
-
-/* Add new kernel dependency.  */
-
-void
-hsa_add_kernel_dependency (tree caller, const char *called_function)
-{
-  if (hsa_decl_kernel_dependencies == NULL)
-    hsa_decl_kernel_dependencies = new hash_map<tree, vec<const char *> *> ();
-
-  vec <const char *> *s = NULL;
-  vec <const char *> **slot = hsa_decl_kernel_dependencies->get (caller);
-  if (slot == NULL)
-    {
-      s = new vec <const char *> ();
-      hsa_decl_kernel_dependencies->put (caller, s);
-    }
-  else
-    s = *slot;
-
-  s->safe_push (called_function);
-}
-
-/* Expansion to HSA needs a few gc roots to hold types, constructors etc.  In
-   order to minimize the number of GTY roots, we'll root them all in the
-   following array.  The individual elements should only be accessed by the
-   very simple getters (of a pointer-to-tree) below.  */
-
-static GTY(()) tree hsa_tree_gt_roots[3];
-
-tree *
-hsa_get_ctor_statements (void)
-{
-  return &hsa_tree_gt_roots[0];
-}
-
-tree *
-hsa_get_dtor_statements (void)
-{
-  return &hsa_tree_gt_roots[1];
-}
-
-tree *
-hsa_get_kernel_dispatch_type (void)
-{
-  return &hsa_tree_gt_roots[2];
-}
-
-/* Modify the name P in-place so that it is a valid HSA identifier.  */
-
-void
-hsa_sanitize_name (char *p)
-{
-  for (; *p; p++)
-    if (*p == '.' || *p == '-')
-      *p = '_';
-}
-
-/* Clone the name P, set trailing ampersand and sanitize the name.  */
-
-char *
-hsa_brig_function_name (const char *p)
-{
-  unsigned len = strlen (p);
-  char *buf = XNEWVEC (char, len + 2);
-
-  buf[0] = '&';
-  buf[len + 1] = '\0';
-  memcpy (buf + 1, p, len);
-
-  hsa_sanitize_name (buf);
-  return buf;
-}
-
-/* Add a flatten attribute and disable vectorization for gpu implementation
-   function decl GDECL.  */
-
-void hsa_summary_t::process_gpu_implementation_attributes (tree gdecl)
-{
-  DECL_ATTRIBUTES (gdecl)
-    = tree_cons (get_identifier ("flatten"), NULL_TREE,
-                DECL_ATTRIBUTES (gdecl));
-
-  tree fn_opts = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (gdecl);
-  if (fn_opts == NULL_TREE)
-    fn_opts = optimization_default_node;
-  fn_opts = copy_node (fn_opts);
-  TREE_OPTIMIZATION (fn_opts)->x_flag_tree_loop_vectorize = false;
-  TREE_OPTIMIZATION (fn_opts)->x_flag_tree_slp_vectorize = false;
-  DECL_FUNCTION_SPECIFIC_OPTIMIZATION (gdecl) = fn_opts;
-}
-
-void
-hsa_summary_t::link_functions (cgraph_node *gpu, cgraph_node *host,
-                              hsa_function_kind kind, bool gridified_kernel_p)
-{
-  hsa_function_summary *gpu_summary = get (gpu);
-  hsa_function_summary *host_summary = get (host);
-
-  gpu_summary->m_kind = kind;
-  host_summary->m_kind = kind;
-
-  gpu_summary->m_gpu_implementation_p = true;
-  host_summary->m_gpu_implementation_p = false;
-
-  gpu_summary->m_gridified_kernel_p = gridified_kernel_p;
-  host_summary->m_gridified_kernel_p = gridified_kernel_p;
-
-  gpu_summary->m_bound_function = host;
-  host_summary->m_bound_function = gpu;
-
-  process_gpu_implementation_attributes (gpu->decl);
-
-  /* Create reference between a kernel and a corresponding host implementation
-     to quarantee LTO streaming to a same LTRANS.  */
-  if (kind == HSA_KERNEL)
-    gpu->create_reference (host, IPA_REF_ADDR);
-}
-
-/* Add a HOST function to HSA summaries.  */
-
-void
-hsa_register_kernel (cgraph_node *host)
-{
-  if (hsa_summaries == NULL)
-    hsa_summaries = new hsa_summary_t (symtab);
-  hsa_function_summary *s = hsa_summaries->get (host);
-  s->m_kind = HSA_KERNEL;
-}
-
-/* Add a pair of functions to HSA summaries.  GPU is an HSA implementation of
-   a HOST function.  */
-
-void
-hsa_register_kernel (cgraph_node *gpu, cgraph_node *host)
-{
-  if (hsa_summaries == NULL)
-    hsa_summaries = new hsa_summary_t (symtab);
-  hsa_summaries->link_functions (gpu, host, HSA_KERNEL, true);
-}
-
-/* Return true if expansion of the current HSA function has already failed.  */
-
-bool
-hsa_seen_error (void)
-{
-  return hsa_cfun->m_seen_error;
-}
-
-/* Mark current HSA function as failed.  */
-
-void
-hsa_fail_cfun (void)
-{
-  hsa_failed_functions->add (hsa_cfun->m_decl);
-  hsa_cfun->m_seen_error = true;
-}
-
-char *
-hsa_internal_fn::name ()
-{
-  char *name = xstrdup (internal_fn_name (m_fn));
-  for (char *ptr = name; *ptr; ptr++)
-    *ptr = TOLOWER (*ptr);
-
-  const char *suffix = NULL;
-  if (m_type_bit_size == 32)
-    suffix = "f";
-
-  if (suffix)
-    {
-      char *name2 = concat (name, suffix, NULL);
-      free (name);
-      name = name2;
-    }
-
-  hsa_sanitize_name (name);
-  return name;
-}
-
-unsigned
-hsa_internal_fn::get_arity ()
-{
-  switch (m_fn)
-    {
-    case IFN_ACOS:
-    case IFN_ASIN:
-    case IFN_ATAN:
-    case IFN_COS:
-    case IFN_EXP:
-    case IFN_EXP10:
-    case IFN_EXP2:
-    case IFN_EXPM1:
-    case IFN_LOG:
-    case IFN_LOG10:
-    case IFN_LOG1P:
-    case IFN_LOG2:
-    case IFN_LOGB:
-    case IFN_SIGNIFICAND:
-    case IFN_SIN:
-    case IFN_SQRT:
-    case IFN_TAN:
-    case IFN_CEIL:
-    case IFN_FLOOR:
-    case IFN_NEARBYINT:
-    case IFN_RINT:
-    case IFN_ROUND:
-    case IFN_TRUNC:
-      return 1;
-    case IFN_ATAN2:
-    case IFN_COPYSIGN:
-    case IFN_FMOD:
-    case IFN_POW:
-    case IFN_REMAINDER:
-    case IFN_SCALB:
-    case IFN_LDEXP:
-      return 2;
-    case IFN_CLRSB:
-    case IFN_CLZ:
-    case IFN_CTZ:
-    case IFN_FFS:
-    case IFN_PARITY:
-    case IFN_POPCOUNT:
-    default:
-      /* As we produce sorry message for unknown internal functions,
-        reaching this label is definitely a bug.  */
-      gcc_unreachable ();
-    }
-}
-
-BrigType16_t
-hsa_internal_fn::get_argument_type (int n)
-{
-  switch (m_fn)
-    {
-    case IFN_ACOS:
-    case IFN_ASIN:
-    case IFN_ATAN:
-    case IFN_COS:
-    case IFN_EXP:
-    case IFN_EXP10:
-    case IFN_EXP2:
-    case IFN_EXPM1:
-    case IFN_LOG:
-    case IFN_LOG10:
-    case IFN_LOG1P:
-    case IFN_LOG2:
-    case IFN_LOGB:
-    case IFN_SIGNIFICAND:
-    case IFN_SIN:
-    case IFN_SQRT:
-    case IFN_TAN:
-    case IFN_CEIL:
-    case IFN_FLOOR:
-    case IFN_NEARBYINT:
-    case IFN_RINT:
-    case IFN_ROUND:
-    case IFN_TRUNC:
-    case IFN_ATAN2:
-    case IFN_COPYSIGN:
-    case IFN_FMOD:
-    case IFN_POW:
-    case IFN_REMAINDER:
-    case IFN_SCALB:
-      return hsa_float_for_bitsize (m_type_bit_size);
-    case IFN_LDEXP:
-      {
-       if (n == -1 || n == 0)
-         return hsa_float_for_bitsize (m_type_bit_size);
-       else
-         return BRIG_TYPE_S32;
-      }
-    default:
-      /* As we produce sorry message for unknown internal functions,
-        reaching this label is definitely a bug.  */
-      gcc_unreachable ();
-    }
-}
-
-#include "gt-hsa.h"
diff --git a/gcc/hsa.h b/gcc/hsa.h
deleted file mode 100644 (file)
index a74f2d9..0000000
--- a/gcc/hsa.h
+++ /dev/null
@@ -1,1412 +0,0 @@
-/* HSAIL and BRIG related macros and definitions.
-   Copyright (C) 2013-2017 Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3.  If not see
-<http://www.gnu.org/licenses/>.  */
-
-#ifndef HSA_H
-#define HSA_H
-
-#include "hsa-brig-format.h"
-#include "is-a.h"
-#include "predict.h"
-#include "tree.h"
-#include "vec.h"
-#include "hash-table.h"
-#include "basic-block.h"
-
-
-/* Return true if the compiler should produce HSAIL.  */
-
-static inline bool
-hsa_gen_requested_p (void)
-{
-#ifndef ENABLE_HSA
-  return false;
-#endif
-  return !flag_disable_hsa;
-}
-
-/* Standard warning message if we failed to generate HSAIL for a function.  */
-
-#define HSA_SORRY_MSG "could not emit HSAIL for the function"
-
-class hsa_op_immed;
-class hsa_op_cst_list;
-class hsa_insn_basic;
-class hsa_op_address;
-class hsa_op_reg;
-class hsa_bb;
-
-/* Class representing an input argument, output argument (result) or a
-   variable, that will eventually end up being a symbol directive.  */
-
-struct hsa_symbol
-{
-  /* Constructor.  */
-  hsa_symbol (BrigType16_t type, BrigSegment8_t segment,
-             BrigLinkage8_t linkage, bool global_scope_p = false,
-             BrigAllocation allocation = BRIG_ALLOCATION_AUTOMATIC,
-             BrigAlignment8_t align = BRIG_ALIGNMENT_8);
-
-  /* Return total size of the symbol.  */
-  unsigned HOST_WIDE_INT total_byte_size ();
-
-  /* Fill in those values into the symbol according to DECL, which are
-     determined independently from whether it is parameter, result,
-     or a variable, local or global.  */
-  void fillup_for_decl (tree decl);
-
-  /* Pointer to the original tree, which is PARM_DECL for input parameters and
-     RESULT_DECL for the output parameters.  Also can be CONST_DECL for Fortran
-     constants which need to be put into readonly segment.  */
-  tree m_decl;
-
-  /* Name of the symbol, that will be written into output and dumps.  Can be
-     NULL, see name_number below.  */
-  const char *m_name;
-
-  /* If name is NULL, artificial name will be formed from the segment name and
-     this number.  */
-  int m_name_number;
-
-  /* Once written, this is the offset of the associated symbol directive.  Zero
-     means the symbol has not been written yet.  */
-  unsigned m_directive_offset;
-
-  /* HSA type of the parameter.  */
-  BrigType16_t m_type;
-
-  /* The HSA segment this will eventually end up in.  */
-  BrigSegment8_t m_segment;
-
-  /* The HSA kind of linkage.  */
-  BrigLinkage8_t m_linkage;
-
-  /* Array dimension, if non-zero.  */
-  unsigned HOST_WIDE_INT m_dim;
-
-  /* Constant value, used for string constants.  */
-  hsa_op_immed *m_cst_value;
-
-  /* Is in global scope.  */
-  bool m_global_scope_p;
-
-  /* True if an error has been seen for the symbol.  */
-  bool m_seen_error;
-
-  /* Symbol allocation.  */
-  BrigAllocation m_allocation;
-
-  /* Flag used for global variables if a variable is already emitted or not.  */
-  bool m_emitted_to_brig;
-
-  /* Alignment of the symbol.  */
-  BrigAlignment8_t m_align;
-
-private:
-  /* Default constructor.  */
-  hsa_symbol ();
-};
-
-/* Abstract class for HSA instruction operands.  */
-
-class hsa_op_base
-{
-public:
-  /* Next operand scheduled to be written when writing BRIG operand
-     section.  */
-  hsa_op_base *m_next;
-
-  /* Offset to which the associated operand structure will be written.  Zero if
-     yet not scheduled for writing.  */
-  unsigned m_brig_op_offset;
-
-  /* The type of a particular operand.  */
-  BrigKind16_t m_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.  */
-
-class hsa_op_with_type : public hsa_op_base
-{
-public:
-  /* The type.  */
-  BrigType16_t m_type;
-
-  /* Convert an operand to a destination type DTYPE and attach insns
-     to HBB if needed.  */
-  hsa_op_with_type *get_in_type (BrigType16_t dtype, hsa_bb *hbb);
-
-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.  */
-
-class hsa_op_immed : public hsa_op_with_type
-{
-public:
-  hsa_op_immed (tree tree_val, bool min32int = true);
-  hsa_op_immed (HOST_WIDE_INT int_value, BrigType16_t type);
-  void *operator new (size_t);
-  ~hsa_op_immed ();
-  void set_type (BrigKind16_t t);
-
-  /* Function returns pointer to a buffer that contains binary representation
-     of the immeadiate value.  The buffer has length of BRIG_SIZE and
-     a caller is responsible for deallocation of the buffer.  */
-  char *emit_to_buffer (unsigned *brig_size);
-
-  /* Value as represented by middle end.  */
-  tree m_tree_value;
-
-  /* Integer value representation.  */
-  HOST_WIDE_INT m_int_value;
-
-private:
-  /* Make the default constructor inaccessible.  */
-  hsa_op_immed ();
-  /* 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.  */
-
-template <>
-template <>
-inline bool
-is_a_helper <hsa_op_immed *>::test (hsa_op_base *p)
-{
-  return p->m_kind == BRIG_KIND_OPERAND_CONSTANT_BYTES;
-}
-
-/* Likewise, but for a more specified base. */
-
-template <>
-template <>
-inline bool
-is_a_helper <hsa_op_immed *>::test (hsa_op_with_type *p)
-{
-  return p->m_kind == BRIG_KIND_OPERAND_CONSTANT_BYTES;
-}
-
-
-/* HSA register operand.  */
-
-class hsa_op_reg : public hsa_op_with_type
-{
-  friend class hsa_insn_basic;
-  friend class hsa_insn_phi;
-public:
-  hsa_op_reg (BrigType16_t t);
-  void *operator new (size_t);
-
-  /* Verify register operand.  */
-  void verify_ssa ();
-
-  /* If NON-NULL, gimple SSA that we come from.  NULL if none.  */
-  tree m_gimple_ssa;
-
-  /* Defining instruction while still in the SSA.  */
-  hsa_insn_basic *m_def_insn;
-
-  /* If the register allocator decides to spill the register, this is the
-     appropriate spill symbol.  */
-  hsa_symbol *m_spill_sym;
-
-  /* Number of this register structure in the order in which they were
-     allocated.  */
-  int m_order;
-  int m_lr_begin, m_lr_end;
-
-  /* Zero if the register is not yet allocated.  After, allocation, this must
-     be 'c', 's', 'd' or 'q'.  */
-  char m_reg_class;
-  /* If allocated, the number of the HW register (within its HSA register
-     class).  */
-  char m_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 *) {}
-  /* Set definition where the register is defined.  */
-  void set_definition (hsa_insn_basic *insn);
-  /* Uses of the value while still in SSA.  */
-  auto_vec <hsa_insn_basic *> m_uses;
-};
-
-/* Report whether or not P is a register operand.  */
-
-template <>
-template <>
-inline bool
-is_a_helper <hsa_op_reg *>::test (hsa_op_base *p)
-{
-  return p->m_kind == BRIG_KIND_OPERAND_REGISTER;
-}
-
-/* Report whether or not P is a register operand.  */
-
-template <>
-template <>
-inline bool
-is_a_helper <hsa_op_reg *>::test (hsa_op_with_type *p)
-{
-  return p->m_kind == BRIG_KIND_OPERAND_REGISTER;
-}
-
-/* An address HSA operand.  */
-
-class hsa_op_address : public hsa_op_base
-{
-public:
-  /* 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.  */
-  hsa_op_address (hsa_symbol *sym, hsa_op_reg *reg,
-                 HOST_WIDE_INT offset = 0);
-
-  void *operator new (size_t);
-
-  /* Set up a new address operand consisting of base symbol SYM and
-     immediate OFFSET.  If the machine model is not large and offset is 64 bit,
-     the upper, 32 bits have to be zero.  */
-  hsa_op_address (hsa_symbol *sym, HOST_WIDE_INT offset = 0);
-
-  /* Set up a new address operand consisting of 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.  */
-  hsa_op_address (hsa_op_reg *reg, HOST_WIDE_INT offset = 0);
-
-  /* Symbol base of the address.  Can be NULL if there is none.  */
-  hsa_symbol *m_symbol;
-
-  /* Register offset.  Can be NULL if there is none.  */
-  hsa_op_reg *m_reg;
-
-  /* Immediate byte offset.  */
-  HOST_WIDE_INT m_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.  */
-
-template <>
-template <>
-inline bool
-is_a_helper <hsa_op_address *>::test (hsa_op_base *p)
-{
-  return p->m_kind == BRIG_KIND_OPERAND_ADDRESS;
-}
-
-/* A reference to code HSA operand.  It can be either reference
-   to a start of a BB or a start of a function.  */
-
-class hsa_op_code_ref : public hsa_op_base
-{
-public:
-  hsa_op_code_ref ();
-
-  /* Offset in the code section that this refers to.  */
-  unsigned m_directive_offset;
-};
-
-/* Report whether or not P is a code reference operand.  */
-
-template <>
-template <>
-inline bool
-is_a_helper <hsa_op_code_ref *>::test (hsa_op_base *p)
-{
-  return p->m_kind == BRIG_KIND_OPERAND_CODE_REF;
-}
-
-/* Code list HSA operand.  */
-
-class hsa_op_code_list: public hsa_op_base
-{
-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> m_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.  */
-
-template <>
-template <>
-inline bool
-is_a_helper <hsa_op_code_list *>::test (hsa_op_base *p)
-{
-  return p->m_kind == BRIG_KIND_OPERAND_CODE_LIST;
-}
-
-/* Operand list HSA operand.  */
-
-class hsa_op_operand_list: public hsa_op_base
-{
-public:
-  hsa_op_operand_list (unsigned elements);
-  ~hsa_op_operand_list ();
-  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> m_offsets;
-private:
-  /* Make the default constructor inaccessible.  */
-  hsa_op_operand_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.  */
-
-template <>
-template <>
-inline bool
-is_a_helper <hsa_op_operand_list *>::test (hsa_op_base *p)
-{
-  return p->m_kind == BRIG_KIND_OPERAND_OPERAND_LIST;
-}
-
-/* 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_ARG_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.  */
-
-class hsa_insn_basic
-{
-public:
-  hsa_insn_basic (unsigned nops, int opc);
-  hsa_insn_basic (unsigned nops, int opc, BrigType16_t t,
-                 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);
-  void set_op (int index, hsa_op_base *op);
-  hsa_op_base *get_op (int index);
-  hsa_op_base **get_op_addr (int index);
-  unsigned int operand_count ();
-  void verify ();
-  unsigned input_count ();
-  unsigned num_used_ops ();
-  void set_output_in_type (hsa_op_reg *dest, unsigned op_index, hsa_bb *hbb);
-  bool op_output_p (unsigned opnum);
-
-  /* The previous and next instruction in the basic block.  */
-  hsa_insn_basic *m_prev, *m_next;
-
-  /* Basic block this instruction belongs to.  */
-  basic_block m_bb;
-
-  /* Operand code distinguishing different types of instructions.  Eventually
-     these should only be BRIG_INST_* values from the BrigOpcode16_t range but
-     initially we use negative values for PHI nodes and such.  */
-  int m_opcode;
-
-  /* Linearized number assigned to the instruction by HSA RA.  */
-  int m_number;
-
-  /* Type of the destination of the operations.  */
-  BrigType16_t m_type;
-
-  /* BRIG offset of the instruction in code section.  */
-  unsigned int m_brig_offset;
-
-private:
-  /* 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 *) {}
-  /* 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> m_operands;
-};
-
-/* Class representing a PHI node of the SSA form of HSA virtual
-   registers.  */
-
-class hsa_insn_phi : public hsa_insn_basic
-{
-public:
-  hsa_insn_phi (unsigned nops, hsa_op_reg *dst);
-
-  /* Destination.  */
-  hsa_op_reg *m_dest;
-
-private:
-  /* Make the default constructor inaccessible.  */
-  hsa_insn_phi () : hsa_insn_basic (1, HSA_OPCODE_PHI) {}
-};
-
-/* Report whether or not P is a PHI node.  */
-
-template <>
-template <>
-inline bool
-is_a_helper <hsa_insn_phi *>::test (hsa_insn_basic *p)
-{
-  return p->m_opcode == HSA_OPCODE_PHI;
-}
-
-/* HSA instruction for  */
-class hsa_insn_br : public hsa_insn_basic
-{
-public:
-  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);
-
-  /* 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 (0, BRIG_OPCODE_BR) {}
-};
-
-/* 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_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);
-
-private:
-  /* Make the default constructor inaccessible.  */
-  hsa_insn_cbr () : hsa_insn_br (0, BRIG_OPCODE_CBR, BRIG_TYPE_B1,
-                                BRIG_WIDTH_1) {}
-};
-
-/* 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.  */
-
-class hsa_insn_sbr : public hsa_insn_basic
-{
-public:
-  hsa_insn_sbr (hsa_op_reg *index, unsigned jump_count);
-
-  /* Default destructor.  */
-  ~hsa_insn_sbr ();
-
-  void replace_all_labels (basic_block old_bb, basic_block new_bb);
-
-  /* Width as described in HSA documentation.  */
-  BrigWidth8_t m_width;
-
-  /* Jump table.  */
-  vec <basic_block> m_jump_table;
-
-  /* Code list for label references.  */
-  hsa_op_code_list *m_label_code_list;
-
-private:
-  /* Make the default constructor inaccessible.  */
-  hsa_insn_sbr () : hsa_insn_basic (1, BRIG_OPCODE_SBR) {}
-};
-
-/* Report whether P is a switch branching instruction.  */
-
-template <>
-template <>
-inline bool
-is_a_helper <hsa_insn_sbr *>::test (hsa_insn_basic *p)
-{
-  return p->m_opcode == BRIG_OPCODE_SBR;
-}
-
-/* HSA instruction for comparisons.  */
-
-class hsa_insn_cmp : public hsa_insn_basic
-{
-public:
-  hsa_insn_cmp (BrigCompareOperation8_t cmp, BrigType16_t t,
-               hsa_op_base *arg0 = NULL, hsa_op_base *arg1 = NULL,
-               hsa_op_base *arg2 = NULL);
-
-  /* Source type should be derived from operand types.  */
-
-  /* The comparison operation.  */
-  BrigCompareOperation8_t m_compare;
-
-  /* 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) {}
-};
-
-/* Report whether or not P is a comparison instruction.  */
-
-template <>
-template <>
-inline bool
-is_a_helper <hsa_insn_cmp *>::test (hsa_insn_basic *p)
-{
-  return p->m_opcode == BRIG_OPCODE_CMP;
-}
-
-/* HSA instruction for memory operations.  */
-
-class hsa_insn_mem : public hsa_insn_basic
-{
-public:
-  hsa_insn_mem (int opc, BrigType16_t t, hsa_op_base *arg0, hsa_op_base *arg1);
-
-  /* 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 m_align;
-
-  /* HSA equiv class, basically an alias set number.  */
-  uint8_t m_equiv_class;
-
-  /* TODO:  Add width modifier, perhaps also other things.  */
-protected:
-  hsa_insn_mem (unsigned nops, int opc, BrigType16_t t,
-               hsa_op_base *arg0 = NULL, hsa_op_base *arg1 = NULL,
-               hsa_op_base *arg2 = NULL, hsa_op_base *arg3 = NULL);
-
-private:
-  /* Make the default constructor inaccessible.  */
-  hsa_insn_mem () : hsa_insn_basic (1, BRIG_OPCODE_LD) {}
-};
-
-/* Report whether or not P is a memory instruction.  */
-
-template <>
-template <>
-inline bool
-is_a_helper <hsa_insn_mem *>::test (hsa_insn_basic *p)
-{
-  return (p->m_opcode == BRIG_OPCODE_LD
-         || p->m_opcode == BRIG_OPCODE_ST);
-}
-
-/* HSA instruction for atomic operations.  */
-
-class hsa_insn_atomic : public hsa_insn_mem
-{
-public:
-  hsa_insn_atomic (int nops, int opc, enum BrigAtomicOperation aop,
-                  BrigType16_t t, BrigMemoryOrder memorder,
-                  hsa_op_base *arg0 = NULL, hsa_op_base *arg1 = NULL,
-                  hsa_op_base *arg2 = NULL, hsa_op_base *arg3 = NULL);
-
-  /* The operation itself.  */
-  enum BrigAtomicOperation m_atomicop;
-
-  /* Things like acquire/release/aligned.  */
-  enum BrigMemoryOrder m_memoryorder;
-
-  /* Scope of the atomic operation.  */
-  enum BrigMemoryScope m_memoryscope;
-
-private:
-  /* Make the default constructor inaccessible.  */
-  hsa_insn_atomic () : hsa_insn_mem (1, BRIG_KIND_NONE, BRIG_TYPE_NONE) {}
-};
-
-/* Report whether or not P is an atomic instruction.  */
-
-template <>
-template <>
-inline bool
-is_a_helper <hsa_insn_atomic *>::test (hsa_insn_basic *p)
-{
-  return (p->m_opcode == BRIG_OPCODE_ATOMIC
-         || p->m_opcode == BRIG_OPCODE_ATOMICNORET);
-}
-
-/* HSA instruction for signal operations.  */
-
-class hsa_insn_signal : public hsa_insn_basic
-{
-public:
-  hsa_insn_signal (int nops, int opc, enum BrigAtomicOperation sop,
-                  BrigType16_t t, BrigMemoryOrder memorder,
-                  hsa_op_base *arg0 = NULL, hsa_op_base *arg1 = NULL,
-                  hsa_op_base *arg2 = NULL, hsa_op_base *arg3 = NULL);
-
-  /* Things like acquire/release/aligned.  */
-  enum BrigMemoryOrder m_memory_order;
-
-  /* The operation itself.  */
-  enum BrigAtomicOperation m_signalop;
-};
-
-/* Report whether or not P is a signal instruction.  */
-
-template <>
-template <>
-inline bool
-is_a_helper <hsa_insn_signal *>::test (hsa_insn_basic *p)
-{
-  return (p->m_opcode == BRIG_OPCODE_SIGNAL
-         || p->m_opcode == BRIG_OPCODE_SIGNALNORET);
-}
-
-/* HSA instruction to convert between flat addressing and segments.  */
-
-class hsa_insn_seg : public hsa_insn_basic
-{
-public:
-  hsa_insn_seg (int opc, BrigType16_t destt, BrigType16_t srct,
-               BrigSegment8_t seg, hsa_op_base *arg0, hsa_op_base *arg1);
-
-  /* Source type.  Depends on the source addressing/segment.  */
-  BrigType16_t m_src_type;
-  /* The segment we are converting from or to.  */
-  BrigSegment8_t m_segment;
-private:
-  /* Make the default constructor inaccessible.  */
-  hsa_insn_seg () : hsa_insn_basic (1, BRIG_OPCODE_STOF) {}
-};
-
-/* Report whether or not P is a segment conversion instruction.  */
-
-template <>
-template <>
-inline bool
-is_a_helper <hsa_insn_seg *>::test (hsa_insn_basic *p)
-{
-  return (p->m_opcode == BRIG_OPCODE_STOF
-         || p->m_opcode == BRIG_OPCODE_FTOS);
-}
-
-/* Class for internal functions for purpose of HSA emission.  */
-
-class hsa_internal_fn
-{
-public:
-  hsa_internal_fn (enum internal_fn fn, unsigned type_bit_size):
-    m_fn (fn), m_type_bit_size (type_bit_size), m_offset (0) {}
-
-  hsa_internal_fn (const hsa_internal_fn *f):
-    m_fn (f->m_fn), m_type_bit_size (f->m_type_bit_size),
-    m_offset (f->m_offset) {}
-
-  /* Return arity of the internal function.  */
-  unsigned get_arity ();
-
-  /* Return BRIG type of N-th argument, if -1 is passed, return value type
-     is received.  */
-  BrigType16_t get_argument_type (int n);
-
-  /* Return function name.  The memory must be released by a caller.  */
-  char *name ();
-
-  /* Internal function.  */
-  enum internal_fn m_fn;
-
-  /* Bit width of return type.  */
-  unsigned m_type_bit_size;
-
-  /* BRIG offset of declaration of the function.  */
-  BrigCodeOffset32_t m_offset;
-};
-
-/* HSA instruction for function call.  */
-
-class hsa_insn_call : public hsa_insn_basic
-{
-public:
-  hsa_insn_call (tree callee);
-  hsa_insn_call (hsa_internal_fn *fn);
-
-  /* Default destructor.  */
-  ~hsa_insn_call ();
-
-  /* Called function.  */
-  tree m_called_function;
-
-  /* Called internal function.  */
-  hsa_internal_fn *m_called_internal_fn;
-
-  /* Input formal arguments.  */
-  auto_vec <hsa_symbol *> m_input_args;
-
-  /* Input arguments store instructions.  */
-  auto_vec <hsa_insn_mem *> m_input_arg_insns;
-
-  /* Output argument, can be NULL for void functions.  */
-  hsa_symbol *m_output_arg;
-
-  /* Called function code reference.  */
-  hsa_op_code_ref m_func;
-
-  /* Code list for arguments of the function.  */
-  hsa_op_code_list *m_args_code_list;
-
-  /* Code list for result of the function.  */
-  hsa_op_code_list *m_result_code_list;
-private:
-  /* Make the default constructor inaccessible.  */
-  hsa_insn_call () : hsa_insn_basic (0, BRIG_OPCODE_CALL) {}
-};
-
-/* Report whether or not P is a call instruction.  */
-
-template <>
-template <>
-inline bool
-is_a_helper <hsa_insn_call *>::test (hsa_insn_basic *p)
-{
-  return (p->m_opcode == BRIG_OPCODE_CALL);
-}
-
-/* HSA call instruction block encapsulates definition of arguments,
-   result type, corresponding loads and a possible store.
-   Moreover, it contains a single call instruction.
-   Emission of the instruction will produce multiple
-   HSAIL instructions.  */
-
-class hsa_insn_arg_block : public hsa_insn_basic
-{
-public:
-  hsa_insn_arg_block (BrigKind brig_kind, hsa_insn_call * call);
-
-  /* Kind of argument block.  */
-  BrigKind m_kind;
-
-  /* Call instruction.  */
-  hsa_insn_call *m_call_insn;
-};
-
-/* Report whether or not P is a call block instruction.  */
-
-template <>
-template <>
-inline bool
-is_a_helper <hsa_insn_arg_block *>::test (hsa_insn_basic *p)
-{
-  return (p->m_opcode == HSA_OPCODE_ARG_BLOCK);
-}
-
-/* HSA comment instruction.  */
-
-class hsa_insn_comment: public hsa_insn_basic
-{
-public:
-  /* Constructor of class representing the comment in HSAIL.  */
-  hsa_insn_comment (const char *s);
-
-  /* Default destructor.  */
-  ~hsa_insn_comment ();
-
-  char *m_comment;
-};
-
-/* Report whether or not P is a call block instruction.  */
-
-template <>
-template <>
-inline bool
-is_a_helper <hsa_insn_comment *>::test (hsa_insn_basic *p)
-{
-  return (p->m_opcode == BRIG_KIND_DIRECTIVE_COMMENT);
-}
-
-/* HSA queue instruction.  */
-
-class hsa_insn_queue: public hsa_insn_basic
-{
-public:
-  hsa_insn_queue (int nops, int opcode, BrigSegment segment,
-                 BrigMemoryOrder memory_order,
-                 hsa_op_base *arg0 = NULL, hsa_op_base *arg1 = NULL,
-                 hsa_op_base *arg2 = NULL, hsa_op_base *arg3 = NULL);
-
-  /* Destructor.  */
-  ~hsa_insn_queue ();
-
-  /* Segment used to refer to the queue.  Must be global or flat.  */
-  BrigSegment m_segment;
-  /* Memory order used to specify synchronization.  */
-  BrigMemoryOrder m_memory_order;
-};
-
-/* Report whether or not P is a queue instruction.  */
-
-template <>
-template <>
-inline bool
-is_a_helper <hsa_insn_queue *>::test (hsa_insn_basic *p)
-{
-  return (p->m_opcode == BRIG_OPCODE_ADDQUEUEWRITEINDEX
-         || p->m_opcode == BRIG_OPCODE_CASQUEUEWRITEINDEX
-         || p->m_opcode == BRIG_OPCODE_LDQUEUEREADINDEX
-         || p->m_opcode == BRIG_OPCODE_LDQUEUEWRITEINDEX
-         || p->m_opcode == BRIG_OPCODE_STQUEUEREADINDEX
-         || p->m_opcode == BRIG_OPCODE_STQUEUEWRITEINDEX);
-}
-
-/* HSA source type instruction.  */
-
-class hsa_insn_srctype: public hsa_insn_basic
-{
-public:
-  hsa_insn_srctype (int nops, BrigOpcode opcode, BrigType16_t destt,
-                  BrigType16_t srct, hsa_op_base *arg0, hsa_op_base *arg1,
-                  hsa_op_base *arg2);
-
-  /* Source type.  */
-  BrigType16_t m_source_type;
-
-  /* Destructor.  */
-  ~hsa_insn_srctype ();
-};
-
-/* Report whether or not P is a source type instruction.  */
-
-template <>
-template <>
-inline bool
-is_a_helper <hsa_insn_srctype *>::test (hsa_insn_basic *p)
-{
-  return (p->m_opcode == BRIG_OPCODE_POPCOUNT
-         || p->m_opcode == BRIG_OPCODE_FIRSTBIT
-         || p->m_opcode == BRIG_OPCODE_LASTBIT);
-}
-
-/* HSA packed instruction.  */
-
-class hsa_insn_packed : public hsa_insn_srctype
-{
-public:
-  hsa_insn_packed (int nops, BrigOpcode opcode, BrigType16_t destt,
-                  BrigType16_t srct, hsa_op_base *arg0, hsa_op_base *arg1,
-                  hsa_op_base *arg2);
-
-  /* Operand list for an operand of the instruction.  */
-  hsa_op_operand_list *m_operand_list;
-
-  /* Destructor.  */
-  ~hsa_insn_packed ();
-};
-
-/* Report whether or not P is a combine instruction.  */
-
-template <>
-template <>
-inline bool
-is_a_helper <hsa_insn_packed *>::test (hsa_insn_basic *p)
-{
-  return (p->m_opcode == BRIG_OPCODE_COMBINE
-         || p->m_opcode == BRIG_OPCODE_EXPAND);
-}
-
-/* HSA convert instruction.  */
-
-class hsa_insn_cvt: public hsa_insn_basic
-{
-public:
-  hsa_insn_cvt (hsa_op_with_type *dest, hsa_op_with_type *src);
-};
-
-/* Report whether or not P is a convert instruction.  */
-
-template <>
-template <>
-inline bool
-is_a_helper <hsa_insn_cvt *>::test (hsa_insn_basic *p)
-{
-  return (p->m_opcode == BRIG_OPCODE_CVT);
-}
-
-/* HSA alloca instruction.  */
-
-class hsa_insn_alloca: public hsa_insn_basic
-{
-public:
-  hsa_insn_alloca (hsa_op_with_type *dest, hsa_op_with_type *size,
-                  unsigned alignment = 0);
-
-  /* Required alignment of the allocation.  */
-  BrigAlignment8_t m_align;
-};
-
-/* Report whether or not P is an alloca instruction.  */
-
-template <>
-template <>
-inline bool
-is_a_helper <hsa_insn_alloca *>::test (hsa_insn_basic *p)
-{
-  return (p->m_opcode == BRIG_OPCODE_ALLOCA);
-}
-
-/* Basic block of HSA instructions.  */
-
-class hsa_bb
-{
-public:
-  hsa_bb (basic_block cfg_bb);
-  hsa_bb (basic_block cfg_bb, int idx);
-  ~hsa_bb ();
-
-  /* Append an instruction INSN into the basic block.  */
-  void append_insn (hsa_insn_basic *insn);
-
-  /* Add a PHI instruction.  */
-  void append_phi (hsa_insn_phi *phi);
-
-  /* The real CFG BB that this HBB belongs to.  */
-  basic_block m_bb;
-
-  /* The operand that refers to the label to this BB.  */
-  hsa_op_code_ref m_label_ref;
-
-  /* The first and last instruction.  */
-  hsa_insn_basic *m_first_insn, *m_last_insn;
-  /* The first and last phi node.  */
-  hsa_insn_phi *m_first_phi, *m_last_phi;
-
-  /* Just a number to construct names from.  */
-  int m_index;
-
-  bitmap m_liveout, m_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
-   flow basic_block BB.  */
-
-static inline hsa_bb *
-hsa_bb_for_bb (basic_block bb)
-{
-  return (struct hsa_bb *) bb->aux;
-}
-
-/* Class for hashing local hsa_symbols.  */
-
-struct hsa_noop_symbol_hasher : nofree_ptr_hash <hsa_symbol>
-{
-  static inline hashval_t hash (const value_type);
-  static inline bool equal (const value_type, const compare_type);
-};
-
-/* Hash hsa_symbol.  */
-
-inline hashval_t
-hsa_noop_symbol_hasher::hash (const value_type item)
-{
-  return DECL_UID (item->m_decl);
-}
-
-/* Return true if the DECL_UIDs of decls both symbols refer to are equal.  */
-
-inline bool
-hsa_noop_symbol_hasher::equal (const value_type a, const compare_type b)
-{
-  return (DECL_UID (a->m_decl) == DECL_UID (b->m_decl));
-}
-
-/* Structure that encapsulates intermediate representation of a HSA
-   function.  */
-
-class hsa_function_representation
-{
-public:
-  hsa_function_representation (tree fdecl, bool kernel_p,
-                              unsigned ssa_names_count,
-                              bool modified_cfg = false);
-  hsa_function_representation (hsa_internal_fn *fn);
-  ~hsa_function_representation ();
-
-  /* Builds a shadow register that is utilized to a kernel dispatch.  */
-  hsa_op_reg *get_shadow_reg ();
-
-  /* Return true if we are in a function that has kernel dispatch
-     shadow register.  */
-  bool has_shadow_reg_p ();
-
-  /* The entry/exit blocks don't contain incoming code,
-     but the HSA generator might use them to put code into,
-     so we need hsa_bb instances of them.  */
-  void init_extra_bbs ();
-
-  /* Update CFG dominators if m_modified_cfg flag is set.  */
-  void update_dominance ();
-
-  /* Return linkage of the representation.  */
-  BrigLinkage8_t get_linkage ();
-
-  /* Create a private symbol of requested TYPE.  */
-  hsa_symbol *create_hsa_temporary (BrigType16_t type);
-
-  /* Lookup or create a HSA pseudo register for a given gimple SSA name.  */
-  hsa_op_reg *reg_for_gimple_ssa (tree ssa);
-
-  /* Name of the function.  */
-  char *m_name;
-
-  /* Number of allocated register structures.  */
-  int m_reg_count;
-
-  /* Input arguments.  */
-  vec <hsa_symbol *> m_input_args;
-
-  /* Output argument or NULL if there is none.  */
-  hsa_symbol *m_output_arg;
-
-  /* Hash table of local variable symbols.  */
-  hash_table <hsa_noop_symbol_hasher> *m_local_symbols;
-
-  /* Hash map for string constants.  */
-  hash_map <tree, hsa_symbol *> m_string_constants_map;
-
-  /* Vector of pointers to spill symbols.  */
-  vec <struct hsa_symbol *> m_spill_symbols;
-
-  /* Vector of pointers to global variables and transformed string constants
-     that are used by the function.  */
-  vec <struct hsa_symbol *> m_global_symbols;
-
-  /* Private function artificial variables.  */
-  vec <struct hsa_symbol *> m_private_variables;
-
-  /* Vector of called function declarations.  */
-  vec <tree> m_called_functions;
-
-  /* Vector of used internal functions.  */
-  vec <hsa_internal_fn *> m_called_internal_fns;
-
-  /* Number of HBB BBs.  */
-  int m_hbb_count;
-
-  /* Whether or not we could check and enforce SSA properties.  */
-  bool m_in_ssa;
-
-  /* True if the function is kernel function.  */
-  bool m_kern_p;
-
-  /* True if the function representation is a declaration.  */
-  bool m_declaration_p;
-
-  /* Function declaration tree.  */
-  tree m_decl;
-
-  /* Internal function info is used for declarations of internal functions.  */
-  hsa_internal_fn *m_internal_fn;
-
-  /* Runtime shadow register.  */
-  hsa_op_reg *m_shadow_reg;
-
-  /* Number of kernel dispatched which take place in the function.  */
-  unsigned m_kernel_dispatch_count;
-
-  /* If the function representation contains a kernel dispatch,
-     OMP data size is necessary memory that is used for copying before
-     a kernel dispatch.  */
-  unsigned m_maximum_omp_data_size;
-
-  /* Return true if there's an HSA-specific warning already seen.  */
-  bool m_seen_error;
-
-  /* Counter for temporary symbols created in the function representation.  */
-  unsigned m_temp_symbol_count;
-
-  /* SSA names mapping.  */
-  vec <hsa_op_reg *> m_ssa_map;
-
-  /* Flag whether a function needs update of dominators before RA.  */
-  bool m_modified_cfg;
-};
-
-enum hsa_function_kind
-{
-  HSA_NONE,
-  HSA_KERNEL,
-  HSA_FUNCTION
-};
-
-struct hsa_function_summary
-{
-  /* Default constructor.  */
-  hsa_function_summary ();
-
-  /* Kind of GPU/host function.  */
-  hsa_function_kind m_kind;
-
-  /* Pointer to a cgraph node which is a HSA implementation of the function.
-     In case of the function is a HSA function, the bound function points
-     to the host function.  */
-  cgraph_node *m_bound_function;
-
-  /* Identifies if the function is an HSA function or a host function.  */
-  bool m_gpu_implementation_p;
-
-  /* True if the function is a gridified kernel.  */
-  bool m_gridified_kernel_p;
-};
-
-inline
-hsa_function_summary::hsa_function_summary (): m_kind (HSA_NONE),
-  m_bound_function (NULL), m_gpu_implementation_p (false)
-{
-}
-
-/* Function summary for HSA functions.  */
-class hsa_summary_t: public function_summary <hsa_function_summary *>
-{
-public:
-  hsa_summary_t (symbol_table *table):
-    function_summary<hsa_function_summary *> (table) { }
-
-  /* Couple GPU and HOST as gpu-specific and host-specific implementation of
-     the same function.  KIND determines whether GPU is a host-invokable kernel
-     or gpu-callable function and GRIDIFIED_KERNEL_P is set if the function was
-     gridified in OMP.  */
-
-  void link_functions (cgraph_node *gpu, cgraph_node *host,
-                      hsa_function_kind kind, bool gridified_kernel_p);
-
-private:
-  void process_gpu_implementation_attributes (tree gdecl);
-};
-
-/* OMP simple builtin describes behavior that should be done for
-   the routine.  */
-class omp_simple_builtin
-{
-public:
-  omp_simple_builtin (const char *name, const char *warning_message,
-              bool sorry, hsa_op_immed *return_value = NULL):
-    m_name (name), m_warning_message (warning_message), m_sorry (sorry),
-    m_return_value (return_value)
-  {}
-
-  /* Generate HSAIL instructions for the builtin or produce warning message.  */
-  void generate (gimple *stmt, hsa_bb *hbb);
-
-  /* Name of function.  */
-  const char *m_name;
-
-  /* Warning message.  */
-  const char *m_warning_message;
-
-  /* Flag if we should sorry after the warning message is printed.  */
-  bool m_sorry;
-
-  /* Return value of the function.  */
-  hsa_op_immed *m_return_value;
-
-  /* Emission function.  */
-  void (*m_emit_func) (gimple *stmt, hsa_bb *);
-};
-
-/* Class for hashing hsa_internal_fn.  */
-
-struct hsa_internal_fn_hasher: free_ptr_hash <hsa_internal_fn>
-{
-  static inline hashval_t hash (const value_type);
-  static inline bool equal (const value_type, const compare_type);
-};
-
-/* Hash hsa_symbol.  */
-
-inline hashval_t
-hsa_internal_fn_hasher::hash (const value_type item)
-{
-  return item->m_fn;
-}
-
-/* Return true if the DECL_UIDs of decls both symbols refer to  are equal.  */
-
-inline bool
-hsa_internal_fn_hasher::equal (const value_type a, const compare_type b)
-{
-  return a->m_fn == b->m_fn && a->m_type_bit_size == b->m_type_bit_size;
-}
-
-/* in hsa.c */
-extern struct hsa_function_representation *hsa_cfun;
-extern hash_map <tree, vec <const char *> *> *hsa_decl_kernel_dependencies;
-extern hsa_summary_t *hsa_summaries;
-extern hsa_symbol *hsa_num_threads;
-extern unsigned hsa_kernel_calls_counter;
-extern hash_set <tree> *hsa_failed_functions;
-extern hash_table <hsa_noop_symbol_hasher> *hsa_global_variable_symbols;
-
-bool hsa_callable_function_p (tree fndecl);
-void hsa_init_compilation_unit_data (void);
-void hsa_deinit_compilation_unit_data (void);
-bool hsa_machine_large_p (void);
-bool hsa_full_profile_p (void);
-bool hsa_opcode_floating_bit_insn_p (BrigOpcode16_t);
-unsigned hsa_type_bit_size (BrigType16_t t);
-BrigType16_t hsa_bittype_for_bitsize (unsigned bitsize);
-BrigType16_t hsa_uint_for_bitsize (unsigned bitsize);
-BrigType16_t hsa_float_for_bitsize (unsigned bitsize);
-BrigType16_t hsa_bittype_for_type (BrigType16_t t);
-BrigType16_t hsa_unsigned_type_for_type (BrigType16_t t);
-bool hsa_type_packed_p (BrigType16_t type);
-bool hsa_type_float_p (BrigType16_t type);
-bool hsa_type_integer_p (BrigType16_t type);
-bool hsa_btype_p (BrigType16_t type);
-BrigAlignment8_t hsa_alignment_encoding (unsigned n);
-BrigAlignment8_t hsa_natural_alignment (BrigType16_t type);
-BrigAlignment8_t hsa_object_alignment (tree t);
-unsigned hsa_byte_alignment (BrigAlignment8_t alignment);
-void hsa_destroy_operand (hsa_op_base *op);
-void hsa_destroy_insn (hsa_insn_basic *insn);
-void hsa_add_kern_decl_mapping (tree decl, char *name, unsigned, bool);
-unsigned hsa_get_number_decl_kernel_mappings (void);
-tree hsa_get_decl_kernel_mapping_decl (unsigned i);
-char *hsa_get_decl_kernel_mapping_name (unsigned i);
-unsigned hsa_get_decl_kernel_mapping_omp_size (unsigned i);
-bool hsa_get_decl_kernel_mapping_gridified (unsigned i);
-void hsa_free_decl_kernel_mapping (void);
-tree *hsa_get_ctor_statements (void);
-tree *hsa_get_dtor_statements (void);
-tree *hsa_get_kernel_dispatch_type (void);
-void hsa_add_kernel_dependency (tree caller, const char *called_function);
-void hsa_sanitize_name (char *p);
-char *hsa_brig_function_name (const char *p);
-const char *hsa_get_declaration_name (tree decl);
-void hsa_register_kernel (cgraph_node *host);
-void hsa_register_kernel (cgraph_node *gpu, cgraph_node *host);
-bool hsa_seen_error (void);
-void hsa_fail_cfun (void);
-
-/* In hsa-gen.c.  */
-void hsa_build_append_simple_mov (hsa_op_reg *, hsa_op_base *, hsa_bb *);
-hsa_symbol *hsa_get_spill_symbol (BrigType16_t);
-hsa_symbol *hsa_get_string_cst_symbol (BrigType16_t);
-hsa_op_reg *hsa_spill_in (hsa_insn_basic *, hsa_op_reg *, hsa_op_reg **);
-hsa_op_reg *hsa_spill_out (hsa_insn_basic *, hsa_op_reg *, hsa_op_reg **);
-hsa_bb *hsa_init_new_bb (basic_block);
-hsa_function_representation *hsa_generate_function_declaration (tree decl);
-hsa_function_representation *hsa_generate_internal_fn_decl (hsa_internal_fn *);
-tree hsa_get_host_function (tree decl);
-
-/* In hsa-regalloc.c.  */
-void hsa_regalloc (void);
-
-/* In hsa-brig.c.  */
-extern hash_table <hsa_internal_fn_hasher> *hsa_emitted_internal_decls;
-void hsa_brig_emit_function (void);
-void hsa_output_brig (void);
-unsigned hsa_get_imm_brig_type_len (BrigType16_t type);
-void hsa_brig_emit_omp_symbols (void);
-
-/*  In hsa-dump.c.  */
-const char *hsa_seg_name (BrigSegment8_t);
-void dump_hsa_insn (FILE *f, hsa_insn_basic *insn);
-void dump_hsa_bb (FILE *, hsa_bb *);
-void dump_hsa_cfun (FILE *);
-DEBUG_FUNCTION void debug_hsa_operand (hsa_op_base *opc);
-DEBUG_FUNCTION void debug_hsa_insn (hsa_insn_basic *insn);
-
-union hsa_bytes
-{
-  uint8_t b8;
-  uint16_t b16;
-  uint32_t b32;
-  uint64_t b64;
-};
-
-/* Return true if a function DECL is an HSA implementation.  */
-
-static inline bool
-hsa_gpu_implementation_p (tree decl)
-{
-  if (hsa_summaries == NULL)
-    return false;
-
-  hsa_function_summary *s = hsa_summaries->get (cgraph_node::get_create (decl));
-
-  return s->m_gpu_implementation_p;
-}
-
-#endif /* HSA_H */
index 6a3f660672e7d234962d6f21dae8897836c335c6..af70b0a92307fc3a50c0c5ece4593e4b25410f9d 100644 (file)
@@ -41,7 +41,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "cgraph.h"
 #include "print-tree.h"
 #include "symbol-summary.h"
-#include "hsa.h"
+#include "hsa-common.h"
 
 namespace {
 
index f0e98873e28127cdd6fc666596bf126a7dadb01a..57d9fdea85ace02dff364bd9ee72953e01b6983c 100644 (file)
@@ -56,7 +56,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "cilk.h"
 #include "gomp-constants.h"
 #include "gimple-pretty-print.h"
-#include "hsa.h"
+#include "hsa-common.h"
 
 
 /* OMP region information.  Every parallel and workshare
index e8d78a91abc9463c7f626655d7a91a77832d27c2..6d30ca617b32d5bb8d2fff792b4aa5ad1690c983 100644 (file)
@@ -57,7 +57,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "context.h"
 #include "gomp-constants.h"
 #include "gimple-pretty-print.h"
-#include "hsa.h"
+#include "hsa-common.h"
 
 /* Lowering of OMP parallel and workshare constructs proceeds in two
    phases.  The first phase scans the function looking for OMP statements
index c0f1a2df517c991910e388400bab8d01604c21a9..2335ad716ae7bb8449c49cd2036a8d5cbb7bc60f 100644 (file)
@@ -77,7 +77,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "gcse.h"
 #include "tree-chkp.h"
 #include "omp-offload.h"
-#include "hsa.h"
+#include "hsa-common.h"
 #include "edit-context.h"
 
 #if defined(DBX_DEBUGGING_INFO) || defined(XCOFF_DEBUGGING_INFO)