LCOV - code coverage report
Current view: top level - gcc - hsa-gen.c (source / functions) Hit Total Coverage
Test: gcc.info Lines: 7 3301 0.2 %
Date: 2020-03-28 11:57:23 Functions: 2 184 1.1 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /* A pass for lowering gimple to HSAIL
       2                 :            :    Copyright (C) 2013-2020 Free Software Foundation, Inc.
       3                 :            :    Contributed by Martin Jambor <mjambor@suse.cz> and
       4                 :            :    Martin Liska <mliska@suse.cz>.
       5                 :            : 
       6                 :            : This file is part of GCC.
       7                 :            : 
       8                 :            : GCC is free software; you can redistribute it and/or modify
       9                 :            : it under the terms of the GNU General Public License as published by
      10                 :            : the Free Software Foundation; either version 3, or (at your option)
      11                 :            : any later version.
      12                 :            : 
      13                 :            : GCC is distributed in the hope that it will be useful,
      14                 :            : but WITHOUT ANY WARRANTY; without even the implied warranty of
      15                 :            : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16                 :            : GNU General Public License for more details.
      17                 :            : 
      18                 :            : You should have received a copy of the GNU General Public License
      19                 :            : along with GCC; see the file COPYING3.  If not see
      20                 :            : <http://www.gnu.org/licenses/>.  */
      21                 :            : 
      22                 :            : #include "config.h"
      23                 :            : #include "system.h"
      24                 :            : #include "coretypes.h"
      25                 :            : #include "memmodel.h"
      26                 :            : #include "tm.h"
      27                 :            : #include "is-a.h"
      28                 :            : #include "hash-table.h"
      29                 :            : #include "vec.h"
      30                 :            : #include "tree.h"
      31                 :            : #include "tree-pass.h"
      32                 :            : #include "function.h"
      33                 :            : #include "basic-block.h"
      34                 :            : #include "cfg.h"
      35                 :            : #include "fold-const.h"
      36                 :            : #include "gimple.h"
      37                 :            : #include "gimple-iterator.h"
      38                 :            : #include "bitmap.h"
      39                 :            : #include "dumpfile.h"
      40                 :            : #include "gimple-pretty-print.h"
      41                 :            : #include "diagnostic-core.h"
      42                 :            : #include "gimple-ssa.h"
      43                 :            : #include "tree-phinodes.h"
      44                 :            : #include "stringpool.h"
      45                 :            : #include "tree-vrp.h"
      46                 :            : #include "tree-ssanames.h"
      47                 :            : #include "tree-dfa.h"
      48                 :            : #include "ssa-iterators.h"
      49                 :            : #include "cgraph.h"
      50                 :            : #include "print-tree.h"
      51                 :            : #include "alloc-pool.h"
      52                 :            : #include "symbol-summary.h"
      53                 :            : #include "hsa-common.h"
      54                 :            : #include "cfghooks.h"
      55                 :            : #include "tree-cfg.h"
      56                 :            : #include "cfgloop.h"
      57                 :            : #include "cfganal.h"
      58                 :            : #include "builtins.h"
      59                 :            : #include "gomp-constants.h"
      60                 :            : #include "internal-fn.h"
      61                 :            : #include "builtins.h"
      62                 :            : #include "stor-layout.h"
      63                 :            : #include "stringpool.h"
      64                 :            : #include "attribs.h"
      65                 :            : 
      66                 :            : /* Print a warning message and set that we have seen an error.  */
      67                 :            : 
      68                 :            : #define HSA_SORRY_ATV(location, message, ...) \
      69                 :            :   do \
      70                 :            :   { \
      71                 :            :     hsa_fail_cfun (); \
      72                 :            :     auto_diagnostic_group d; \
      73                 :            :     if (warning_at (EXPR_LOCATION (hsa_cfun->m_decl), OPT_Whsa, \
      74                 :            :                     HSA_SORRY_MSG)) \
      75                 :            :       inform (location, message, __VA_ARGS__); \
      76                 :            :   } \
      77                 :            :   while (false)
      78                 :            : 
      79                 :            : /* Same as previous, but highlight a location.  */
      80                 :            : 
      81                 :            : #define HSA_SORRY_AT(location, message) \
      82                 :            :   do \
      83                 :            :   { \
      84                 :            :     hsa_fail_cfun (); \
      85                 :            :     auto_diagnostic_group d; \
      86                 :            :     if (warning_at (EXPR_LOCATION (hsa_cfun->m_decl), OPT_Whsa, \
      87                 :            :                     HSA_SORRY_MSG)) \
      88                 :            :       inform (location, message); \
      89                 :            :   } \
      90                 :            :   while (false)
      91                 :            : 
      92                 :            : /* Default number of threads used by kernel dispatch.  */
      93                 :            : 
      94                 :            : #define HSA_DEFAULT_NUM_THREADS 64
      95                 :            : 
      96                 :            : /* Following structures are defined in the final version
      97                 :            :    of HSA specification.  */
      98                 :            : 
      99                 :            : /* HSA queue packet is shadow structure, originally provided by AMD.  */
     100                 :            : 
     101                 :            : struct hsa_queue_packet
     102                 :            : {
     103                 :            :   uint16_t header;
     104                 :            :   uint16_t setup;
     105                 :            :   uint16_t workgroup_size_x;
     106                 :            :   uint16_t workgroup_size_y;
     107                 :            :   uint16_t workgroup_size_z;
     108                 :            :   uint16_t reserved0;
     109                 :            :   uint32_t grid_size_x;
     110                 :            :   uint32_t grid_size_y;
     111                 :            :   uint32_t grid_size_z;
     112                 :            :   uint32_t private_segment_size;
     113                 :            :   uint32_t group_segment_size;
     114                 :            :   uint64_t kernel_object;
     115                 :            :   void *kernarg_address;
     116                 :            :   uint64_t reserved2;
     117                 :            :   uint64_t completion_signal;
     118                 :            : };
     119                 :            : 
     120                 :            : /* HSA queue is shadow structure, originally provided by AMD.  */
     121                 :            : 
     122                 :            : struct hsa_queue
     123                 :            : {
     124                 :            :   int type;
     125                 :            :   uint32_t features;
     126                 :            :   void *base_address;
     127                 :            :   uint64_t doorbell_signal;
     128                 :            :   uint32_t size;
     129                 :            :   uint32_t reserved1;
     130                 :            :   uint64_t id;
     131                 :            : };
     132                 :            : 
     133                 :            : static struct obstack hsa_obstack;
     134                 :            : 
     135                 :            : /* List of pointers to all instructions that come from an object allocator.  */
     136                 :            : static vec <hsa_insn_basic *> hsa_instructions;
     137                 :            : 
     138                 :            : /* List of pointers to all operands that come from an object allocator.  */
     139                 :            : static vec <hsa_op_base *> hsa_operands;
     140                 :            : 
     141                 :          0 : hsa_symbol::hsa_symbol ()
     142                 :            :   : m_decl (NULL_TREE), m_name (NULL), m_name_number (0),
     143                 :            :     m_directive_offset (0), m_type (BRIG_TYPE_NONE),
     144                 :            :     m_segment (BRIG_SEGMENT_NONE), m_linkage (BRIG_LINKAGE_NONE), m_dim (0),
     145                 :            :     m_cst_value (NULL), m_global_scope_p (false), m_seen_error (false),
     146                 :          0 :     m_allocation (BRIG_ALLOCATION_AUTOMATIC), m_emitted_to_brig (false)
     147                 :            : {
     148                 :          0 : }
     149                 :            : 
     150                 :            : 
     151                 :          0 : hsa_symbol::hsa_symbol (BrigType16_t type, BrigSegment8_t segment,
     152                 :            :                         BrigLinkage8_t linkage, bool global_scope_p,
     153                 :          0 :                         BrigAllocation allocation, BrigAlignment8_t align)
     154                 :            :   : m_decl (NULL_TREE), m_name (NULL), m_name_number (0),
     155                 :            :     m_directive_offset (0), m_type (type), m_segment (segment),
     156                 :            :     m_linkage (linkage), m_dim (0), m_cst_value (NULL),
     157                 :            :     m_global_scope_p (global_scope_p), m_seen_error (false),
     158                 :          0 :     m_allocation (allocation), m_emitted_to_brig (false), m_align (align)
     159                 :            : {
     160                 :          0 : }
     161                 :            : 
     162                 :            : unsigned HOST_WIDE_INT
     163                 :          0 : hsa_symbol::total_byte_size ()
     164                 :            : {
     165                 :          0 :   unsigned HOST_WIDE_INT s
     166                 :          0 :     = hsa_type_bit_size (~BRIG_TYPE_ARRAY_MASK & m_type);
     167                 :          0 :   gcc_assert (s % BITS_PER_UNIT == 0);
     168                 :          0 :   s /= BITS_PER_UNIT;
     169                 :            : 
     170                 :          0 :   if (m_dim)
     171                 :          0 :     s *= m_dim;
     172                 :            : 
     173                 :          0 :   return s;
     174                 :            : }
     175                 :            : 
     176                 :            : /* Forward declaration.  */
     177                 :            : 
     178                 :            : static BrigType16_t
     179                 :            : hsa_type_for_tree_type (const_tree type, unsigned HOST_WIDE_INT *dim_p,
     180                 :            :                         bool min32int);
     181                 :            : 
     182                 :            : void
     183                 :          0 : hsa_symbol::fillup_for_decl (tree decl)
     184                 :            : {
     185                 :          0 :   m_decl = decl;
     186                 :          0 :   m_type = hsa_type_for_tree_type (TREE_TYPE (decl), &m_dim, false);
     187                 :          0 :   if (hsa_seen_error ())
     188                 :            :     {
     189                 :          0 :       m_seen_error = true;
     190                 :          0 :       return;
     191                 :            :     }
     192                 :            : 
     193                 :          0 :   m_align = MAX (m_align, hsa_natural_alignment (m_type));
     194                 :            : }
     195                 :            : 
     196                 :            : /* Constructor of class representing global HSA function/kernel information and
     197                 :            :    state.  FNDECL is function declaration, KERNEL_P is true if the function
     198                 :            :    is going to become a HSA kernel.  If the function has body, SSA_NAMES_COUNT
     199                 :            :    should be set to number of SSA names used in the function.
     200                 :            :    MODIFIED_CFG is set to true in case we modified control-flow graph
     201                 :            :    of the function.  */
     202                 :            : 
     203                 :          0 : hsa_function_representation::hsa_function_representation
     204                 :          0 :   (tree fdecl, bool kernel_p, unsigned ssa_names_count, bool modified_cfg)
     205                 :            :   : m_name (NULL),
     206                 :            :     m_reg_count (0), m_input_args (vNULL),
     207                 :            :     m_output_arg (NULL), m_spill_symbols (vNULL), m_global_symbols (vNULL),
     208                 :            :     m_private_variables (vNULL), m_called_functions (vNULL),
     209                 :            :     m_called_internal_fns (vNULL), m_hbb_count (0),
     210                 :            :     m_in_ssa (true), m_kern_p (kernel_p), m_declaration_p (false),
     211                 :            :     m_decl (fdecl), m_internal_fn (NULL), m_shadow_reg (NULL),
     212                 :            :     m_kernel_dispatch_count (0), m_maximum_omp_data_size (0),
     213                 :            :     m_seen_error (false), m_temp_symbol_count (0), m_ssa_map (),
     214                 :          0 :     m_modified_cfg (modified_cfg)
     215                 :            : {
     216                 :          0 :   int sym_init_len = (vec_safe_length (cfun->local_decls) / 2) + 1;
     217                 :          0 :   m_local_symbols = new hash_table <hsa_noop_symbol_hasher> (sym_init_len);
     218                 :          0 :   m_ssa_map.safe_grow_cleared (ssa_names_count);
     219                 :          0 : }
     220                 :            : 
     221                 :            : /* Constructor of class representing HSA function information that
     222                 :            :    is derived for an internal function.  */
     223                 :          0 : hsa_function_representation::hsa_function_representation (hsa_internal_fn *fn)
     224                 :            :   : m_reg_count (0), m_input_args (vNULL),
     225                 :            :     m_output_arg (NULL), m_local_symbols (NULL),
     226                 :            :     m_spill_symbols (vNULL), m_global_symbols (vNULL),
     227                 :            :     m_private_variables (vNULL), m_called_functions (vNULL),
     228                 :            :     m_called_internal_fns (vNULL), m_hbb_count (0),
     229                 :            :     m_in_ssa (true), m_kern_p (false), m_declaration_p (true), m_decl (NULL),
     230                 :            :     m_internal_fn (fn), m_shadow_reg (NULL), m_kernel_dispatch_count (0),
     231                 :            :     m_maximum_omp_data_size (0), m_seen_error (false), m_temp_symbol_count (0),
     232                 :          0 :     m_ssa_map () {}
     233                 :            : 
     234                 :            : /* Destructor of class holding function/kernel-wide information and state.  */
     235                 :            : 
     236                 :          0 : hsa_function_representation::~hsa_function_representation ()
     237                 :            : {
     238                 :            :   /* Kernel names are deallocated at the end of BRIG output when deallocating
     239                 :            :      hsa_decl_kernel_mapping.  */
     240                 :          0 :   if (!m_kern_p || m_seen_error)
     241                 :          0 :     free (m_name);
     242                 :            : 
     243                 :          0 :   for (unsigned i = 0; i < m_input_args.length (); i++)
     244                 :          0 :     delete m_input_args[i];
     245                 :          0 :   m_input_args.release ();
     246                 :            : 
     247                 :          0 :   delete m_output_arg;
     248                 :          0 :   delete m_local_symbols;
     249                 :            : 
     250                 :          0 :   for (unsigned i = 0; i < m_spill_symbols.length (); i++)
     251                 :          0 :     delete m_spill_symbols[i];
     252                 :          0 :   m_spill_symbols.release ();
     253                 :            : 
     254                 :            :   hsa_symbol *sym;
     255                 :          0 :   for (unsigned i = 0; i < m_global_symbols.iterate (i, &sym); i++)
     256                 :          0 :     if (sym->m_linkage != BRIG_ALLOCATION_PROGRAM)
     257                 :          0 :       delete sym;
     258                 :          0 :   m_global_symbols.release ();
     259                 :            : 
     260                 :          0 :   for (unsigned i = 0; i < m_private_variables.length (); i++)
     261                 :          0 :     delete m_private_variables[i];
     262                 :          0 :   m_private_variables.release ();
     263                 :          0 :   m_called_functions.release ();
     264                 :          0 :   m_ssa_map.release ();
     265                 :            : 
     266                 :          0 :   for (unsigned i = 0; i < m_called_internal_fns.length (); i++)
     267                 :          0 :     delete m_called_internal_fns[i];
     268                 :          0 : }
     269                 :            : 
     270                 :            : hsa_op_reg *
     271                 :          0 : hsa_function_representation::get_shadow_reg ()
     272                 :            : {
     273                 :            :   /* If we compile a function with kernel dispatch and does not set
     274                 :            :      an optimization level, the function won't be inlined and
     275                 :            :      we return NULL.  */
     276                 :          0 :   if (!m_kern_p)
     277                 :            :     return NULL;
     278                 :            : 
     279                 :          0 :   if (m_shadow_reg)
     280                 :            :     return m_shadow_reg;
     281                 :            : 
     282                 :            :   /* Append the shadow argument.  */
     283                 :          0 :   hsa_symbol *shadow = new hsa_symbol (BRIG_TYPE_U64, BRIG_SEGMENT_KERNARG,
     284                 :          0 :                                        BRIG_LINKAGE_FUNCTION);
     285                 :          0 :   m_input_args.safe_push (shadow);
     286                 :          0 :   shadow->m_name = "hsa_runtime_shadow";
     287                 :            : 
     288                 :          0 :   hsa_op_reg *r = new hsa_op_reg (BRIG_TYPE_U64);
     289                 :          0 :   hsa_op_address *addr = new hsa_op_address (shadow);
     290                 :            : 
     291                 :          0 :   hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, BRIG_TYPE_U64, r, addr);
     292                 :          0 :   hsa_bb_for_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun))->append_insn (mem);
     293                 :          0 :   m_shadow_reg = r;
     294                 :            : 
     295                 :          0 :   return r;
     296                 :            : }
     297                 :            : 
     298                 :          0 : bool hsa_function_representation::has_shadow_reg_p ()
     299                 :            : {
     300                 :          0 :   return m_shadow_reg != NULL;
     301                 :            : }
     302                 :            : 
     303                 :            : void
     304                 :          0 : hsa_function_representation::init_extra_bbs ()
     305                 :            : {
     306                 :          0 :   hsa_init_new_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun));
     307                 :          0 :   hsa_init_new_bb (EXIT_BLOCK_PTR_FOR_FN (cfun));
     308                 :          0 : }
     309                 :            : 
     310                 :            : void
     311                 :          0 : hsa_function_representation::update_dominance ()
     312                 :            : {
     313                 :          0 :   if (m_modified_cfg)
     314                 :            :     {
     315                 :          0 :       free_dominance_info (CDI_DOMINATORS);
     316                 :          0 :       calculate_dominance_info (CDI_DOMINATORS);
     317                 :            :     }
     318                 :          0 : }
     319                 :            : 
     320                 :            : hsa_symbol *
     321                 :          0 : hsa_function_representation::create_hsa_temporary (BrigType16_t type)
     322                 :            : {
     323                 :          0 :   hsa_symbol *s = new hsa_symbol (type, BRIG_SEGMENT_PRIVATE,
     324                 :          0 :                                   BRIG_LINKAGE_FUNCTION);
     325                 :          0 :   s->m_name_number = m_temp_symbol_count++;
     326                 :            : 
     327                 :          0 :   hsa_cfun->m_private_variables.safe_push (s);
     328                 :          0 :   return s;
     329                 :            : }
     330                 :            : 
     331                 :            : BrigLinkage8_t
     332                 :          0 : hsa_function_representation::get_linkage ()
     333                 :            : {
     334                 :          0 :   if (m_internal_fn)
     335                 :            :     return BRIG_LINKAGE_PROGRAM;
     336                 :            : 
     337                 :          0 :   return m_kern_p || TREE_PUBLIC (m_decl) ?
     338                 :          0 :     BRIG_LINKAGE_PROGRAM : BRIG_LINKAGE_MODULE;
     339                 :            : }
     340                 :            : 
     341                 :            : /* Hash map of simple OMP builtins.  */
     342                 :            : static hash_map <nofree_string_hash, omp_simple_builtin> *omp_simple_builtins
     343                 :            :   = NULL;
     344                 :            : 
     345                 :            : /* Warning messages for OMP builtins.  */
     346                 :            : 
     347                 :            : #define HSA_WARN_LOCK_ROUTINE "support for HSA does not implement OpenMP " \
     348                 :            :   "lock routines"
     349                 :            : #define HSA_WARN_TIMING_ROUTINE "support for HSA does not implement OpenMP " \
     350                 :            :   "timing routines"
     351                 :            : #define HSA_WARN_MEMORY_ROUTINE "OpenMP device memory library routines have " \
     352                 :            :   "undefined semantics within target regions, support for HSA ignores them"
     353                 :            : #define HSA_WARN_AFFINITY "Support for HSA does not implement OpenMP " \
     354                 :            :   "affinity feateres"
     355                 :            : 
     356                 :            : /* Initialize hash map with simple OMP builtins.  */
     357                 :            : 
     358                 :            : static void
     359                 :          0 : hsa_init_simple_builtins ()
     360                 :            : {
     361                 :          0 :   if (omp_simple_builtins != NULL)
     362                 :          0 :     return;
     363                 :            : 
     364                 :          0 :   omp_simple_builtins
     365                 :          0 :     = new hash_map <nofree_string_hash, omp_simple_builtin> ();
     366                 :            : 
     367                 :          0 :   omp_simple_builtin omp_builtins[] =
     368                 :            :     {
     369                 :            :       omp_simple_builtin ("omp_get_initial_device", NULL, false,
     370                 :            :                           new hsa_op_immed (GOMP_DEVICE_HOST,
     371                 :          0 :                                             (BrigType16_t) BRIG_TYPE_S32)),
     372                 :            :       omp_simple_builtin ("omp_is_initial_device", NULL, false,
     373                 :          0 :                           new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
     374                 :            :       omp_simple_builtin ("omp_get_dynamic", NULL, false,
     375                 :          0 :                           new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
     376                 :            :       omp_simple_builtin ("omp_set_dynamic", NULL, false, NULL),
     377                 :            :       omp_simple_builtin ("omp_init_lock", HSA_WARN_LOCK_ROUTINE, true),
     378                 :            :       omp_simple_builtin ("omp_init_lock_with_hint", HSA_WARN_LOCK_ROUTINE,
     379                 :            :                           true),
     380                 :            :       omp_simple_builtin ("omp_init_nest_lock_with_hint", HSA_WARN_LOCK_ROUTINE,
     381                 :            :                           true),
     382                 :            :       omp_simple_builtin ("omp_destroy_lock", HSA_WARN_LOCK_ROUTINE, true),
     383                 :            :       omp_simple_builtin ("omp_set_lock", HSA_WARN_LOCK_ROUTINE, true),
     384                 :            :       omp_simple_builtin ("omp_unset_lock", HSA_WARN_LOCK_ROUTINE, true),
     385                 :            :       omp_simple_builtin ("omp_test_lock", HSA_WARN_LOCK_ROUTINE, true),
     386                 :            :       omp_simple_builtin ("omp_get_wtime", HSA_WARN_TIMING_ROUTINE, true),
     387                 :            :       omp_simple_builtin ("omp_get_wtick", HSA_WARN_TIMING_ROUTINE, true),
     388                 :            :       omp_simple_builtin ("omp_target_alloc", HSA_WARN_MEMORY_ROUTINE, false,
     389                 :          0 :                           new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_U64)),
     390                 :            :       omp_simple_builtin ("omp_target_free", HSA_WARN_MEMORY_ROUTINE, false),
     391                 :            :       omp_simple_builtin ("omp_target_is_present", HSA_WARN_MEMORY_ROUTINE,
     392                 :            :                           false,
     393                 :          0 :                           new hsa_op_immed (-1, (BrigType16_t) BRIG_TYPE_S32)),
     394                 :            :       omp_simple_builtin ("omp_target_memcpy", HSA_WARN_MEMORY_ROUTINE, false,
     395                 :          0 :                           new hsa_op_immed (-1, (BrigType16_t) BRIG_TYPE_S32)),
     396                 :            :       omp_simple_builtin ("omp_target_memcpy_rect", HSA_WARN_MEMORY_ROUTINE,
     397                 :            :                           false,
     398                 :          0 :                           new hsa_op_immed (-1, (BrigType16_t) BRIG_TYPE_S32)),
     399                 :            :       omp_simple_builtin ("omp_target_associate_ptr", HSA_WARN_MEMORY_ROUTINE,
     400                 :            :                           false,
     401                 :          0 :                           new hsa_op_immed (-1, (BrigType16_t) BRIG_TYPE_S32)),
     402                 :            :       omp_simple_builtin ("omp_target_disassociate_ptr",
     403                 :            :                           HSA_WARN_MEMORY_ROUTINE,
     404                 :            :                           false,
     405                 :          0 :                           new hsa_op_immed (-1, (BrigType16_t) BRIG_TYPE_S32)),
     406                 :            :       omp_simple_builtin ("omp_set_max_active_levels",
     407                 :            :                           "Support for HSA only allows only one active level, "
     408                 :            :                           "call to omp_set_max_active_levels will be ignored "
     409                 :            :                           "in the generated HSAIL",
     410                 :            :                           false, NULL),
     411                 :            :       omp_simple_builtin ("omp_get_max_active_levels", NULL, false,
     412                 :          0 :                           new hsa_op_immed (1, (BrigType16_t) BRIG_TYPE_S32)),
     413                 :            :       omp_simple_builtin ("omp_in_final", NULL, false,
     414                 :          0 :                           new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
     415                 :            :       omp_simple_builtin ("omp_get_proc_bind", HSA_WARN_AFFINITY, false,
     416                 :          0 :                           new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
     417                 :            :       omp_simple_builtin ("omp_get_num_places", HSA_WARN_AFFINITY, false,
     418                 :          0 :                           new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
     419                 :            :       omp_simple_builtin ("omp_get_place_num_procs", HSA_WARN_AFFINITY, false,
     420                 :          0 :                           new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
     421                 :            :       omp_simple_builtin ("omp_get_place_proc_ids", HSA_WARN_AFFINITY, false,
     422                 :            :                           NULL),
     423                 :            :       omp_simple_builtin ("omp_get_place_num", HSA_WARN_AFFINITY, false,
     424                 :          0 :                           new hsa_op_immed (-1, (BrigType16_t) BRIG_TYPE_S32)),
     425                 :            :       omp_simple_builtin ("omp_get_partition_num_places", HSA_WARN_AFFINITY,
     426                 :            :                           false,
     427                 :          0 :                           new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
     428                 :            :       omp_simple_builtin ("omp_get_partition_place_nums", HSA_WARN_AFFINITY,
     429                 :            :                           false, NULL),
     430                 :            :       omp_simple_builtin ("omp_set_default_device",
     431                 :            :                           "omp_set_default_device has undefined semantics "
     432                 :            :                           "within target regions, support for HSA ignores it",
     433                 :            :                           false, NULL),
     434                 :            :       omp_simple_builtin ("omp_get_default_device",
     435                 :            :                           "omp_get_default_device has undefined semantics "
     436                 :            :                           "within target regions, support for HSA ignores it",
     437                 :            :                           false,
     438                 :          0 :                           new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
     439                 :            :       omp_simple_builtin ("omp_get_num_devices",
     440                 :            :                           "omp_get_num_devices has undefined semantics "
     441                 :            :                           "within target regions, support for HSA ignores it",
     442                 :            :                           false,
     443                 :          0 :                           new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
     444                 :            :       omp_simple_builtin ("omp_get_num_procs", NULL, true, NULL),
     445                 :            :       omp_simple_builtin ("omp_get_cancellation", NULL, true, NULL),
     446                 :            :       omp_simple_builtin ("omp_set_nested", NULL, true, NULL),
     447                 :            :       omp_simple_builtin ("omp_get_nested", NULL, true, NULL),
     448                 :            :       omp_simple_builtin ("omp_set_schedule", NULL, true, NULL),
     449                 :            :       omp_simple_builtin ("omp_get_schedule", NULL, true, NULL),
     450                 :            :       omp_simple_builtin ("omp_get_thread_limit", NULL, true, NULL),
     451                 :            :       omp_simple_builtin ("omp_get_team_size", NULL, true, NULL),
     452                 :            :       omp_simple_builtin ("omp_get_ancestor_thread_num", NULL, true, NULL),
     453                 :            :       omp_simple_builtin ("omp_get_max_task_priority", NULL, true, NULL)
     454                 :          0 :     };
     455                 :            : 
     456                 :          0 :   unsigned count = sizeof (omp_builtins) / sizeof (omp_simple_builtin);
     457                 :            : 
     458                 :          0 :   for (unsigned i = 0; i < count; i++)
     459                 :          0 :     omp_simple_builtins->put (omp_builtins[i].m_name, omp_builtins[i]);
     460                 :            : }
     461                 :            : 
     462                 :            : /* Allocate HSA structures that we need only while generating with this.  */
     463                 :            : 
     464                 :            : static void
     465                 :          0 : hsa_init_data_for_cfun ()
     466                 :            : {
     467                 :          0 :   hsa_init_compilation_unit_data ();
     468                 :          0 :   gcc_obstack_init (&hsa_obstack);
     469                 :          0 : }
     470                 :            : 
     471                 :            : /* Deinitialize HSA subsystem and free all allocated memory.  */
     472                 :            : 
     473                 :            : static void
     474                 :          0 : hsa_deinit_data_for_cfun (void)
     475                 :            : {
     476                 :          0 :   basic_block bb;
     477                 :            : 
     478                 :          0 :   FOR_ALL_BB_FN (bb, cfun)
     479                 :          0 :     if (bb->aux)
     480                 :            :       {
     481                 :          0 :         hsa_bb *hbb = hsa_bb_for_bb (bb);
     482                 :          0 :         hbb->~hsa_bb ();
     483                 :          0 :         bb->aux = NULL;
     484                 :            :       }
     485                 :            : 
     486                 :          0 :   for (unsigned int i = 0; i < hsa_operands.length (); i++)
     487                 :          0 :     hsa_destroy_operand (hsa_operands[i]);
     488                 :            : 
     489                 :          0 :   hsa_operands.release ();
     490                 :            : 
     491                 :          0 :   for (unsigned i = 0; i < hsa_instructions.length (); i++)
     492                 :          0 :     hsa_destroy_insn (hsa_instructions[i]);
     493                 :            : 
     494                 :          0 :   hsa_instructions.release ();
     495                 :            : 
     496                 :          0 :   if (omp_simple_builtins != NULL)
     497                 :            :     {
     498                 :          0 :       delete omp_simple_builtins;
     499                 :          0 :       omp_simple_builtins = NULL;
     500                 :            :     }
     501                 :            : 
     502                 :          0 :   obstack_free (&hsa_obstack, NULL);
     503                 :          0 :   delete hsa_cfun;
     504                 :          0 : }
     505                 :            : 
     506                 :            : /* Return the type which holds addresses in the given SEGMENT.  */
     507                 :            : 
     508                 :            : static BrigType16_t
     509                 :          0 : hsa_get_segment_addr_type (BrigSegment8_t segment)
     510                 :            : {
     511                 :          0 :   switch (segment)
     512                 :            :     {
     513                 :          0 :     case BRIG_SEGMENT_NONE:
     514                 :          0 :       gcc_unreachable ();
     515                 :            : 
     516                 :          0 :     case BRIG_SEGMENT_FLAT:
     517                 :          0 :     case BRIG_SEGMENT_GLOBAL:
     518                 :          0 :     case BRIG_SEGMENT_READONLY:
     519                 :          0 :     case BRIG_SEGMENT_KERNARG:
     520                 :          0 :       return hsa_machine_large_p () ? BRIG_TYPE_U64 : BRIG_TYPE_U32;
     521                 :            : 
     522                 :            :     case BRIG_SEGMENT_GROUP:
     523                 :            :     case BRIG_SEGMENT_PRIVATE:
     524                 :            :     case BRIG_SEGMENT_SPILL:
     525                 :            :     case BRIG_SEGMENT_ARG:
     526                 :            :       return BRIG_TYPE_U32;
     527                 :            :     }
     528                 :          0 :   gcc_unreachable ();
     529                 :            : }
     530                 :            : 
     531                 :            : /* Return integer brig type according to provided SIZE in bytes.  If SIGN
     532                 :            :    is set to true, return signed integer type.  */
     533                 :            : 
     534                 :            : static BrigType16_t
     535                 :          0 : get_integer_type_by_bytes (unsigned size, bool sign)
     536                 :            : {
     537                 :          0 :   if (sign)
     538                 :          0 :     switch (size)
     539                 :            :       {
     540                 :            :       case 1:
     541                 :            :         return BRIG_TYPE_S8;
     542                 :            :       case 2:
     543                 :            :         return BRIG_TYPE_S16;
     544                 :            :       case 4:
     545                 :            :         return BRIG_TYPE_S32;
     546                 :            :       case 8:
     547                 :            :         return BRIG_TYPE_S64;
     548                 :            :       default:
     549                 :            :         break;
     550                 :            :       }
     551                 :            :   else
     552                 :          0 :     switch (size)
     553                 :            :       {
     554                 :            :       case 1:
     555                 :            :         return BRIG_TYPE_U8;
     556                 :            :       case 2:
     557                 :            :         return BRIG_TYPE_U16;
     558                 :            :       case 4:
     559                 :            :         return BRIG_TYPE_U32;
     560                 :            :       case 8:
     561                 :            :         return BRIG_TYPE_U64;
     562                 :            :       default:
     563                 :            :         break;
     564                 :            :       }
     565                 :            : 
     566                 :            :   return 0;
     567                 :            : }
     568                 :            : 
     569                 :            : /* If T points to an integral type smaller than 32 bits, change it to a 32bit
     570                 :            :    equivalent and return the result.  Otherwise just return the result.   */
     571                 :            : 
     572                 :            : static BrigType16_t
     573                 :          0 : hsa_extend_inttype_to_32bit (BrigType16_t t)
     574                 :            : {
     575                 :          0 :   if (t == BRIG_TYPE_U8 || t == BRIG_TYPE_U16)
     576                 :            :     return BRIG_TYPE_U32;
     577                 :          0 :   else if (t == BRIG_TYPE_S8 || t == BRIG_TYPE_S16)
     578                 :          0 :     return BRIG_TYPE_S32;
     579                 :            :   return t;
     580                 :            : }
     581                 :            : 
     582                 :            : /* Return HSA type for tree TYPE, which has to fit into BrigType16_t.  Pointers
     583                 :            :    are assumed to use flat addressing.  If min32int is true, always expand
     584                 :            :    integer types to one that has at least 32 bits.  */
     585                 :            : 
     586                 :            : static BrigType16_t
     587                 :          0 : hsa_type_for_scalar_tree_type (const_tree type, bool min32int)
     588                 :            : {
     589                 :          0 :   HOST_WIDE_INT bsize;
     590                 :          0 :   const_tree base;
     591                 :          0 :   BrigType16_t res = BRIG_TYPE_NONE;
     592                 :            : 
     593                 :          0 :   gcc_checking_assert (TYPE_P (type));
     594                 :          0 :   gcc_checking_assert (!AGGREGATE_TYPE_P (type));
     595                 :          0 :   if (POINTER_TYPE_P (type))
     596                 :          0 :     return hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
     597                 :            : 
     598                 :          0 :   if (TREE_CODE (type) == VECTOR_TYPE)
     599                 :          0 :     base = TREE_TYPE (type);
     600                 :          0 :   else if (TREE_CODE (type) == COMPLEX_TYPE)
     601                 :            :     {
     602                 :          0 :       base = TREE_TYPE (type);
     603                 :          0 :       min32int = true;
     604                 :            :     }
     605                 :            :   else
     606                 :            :     base = type;
     607                 :            : 
     608                 :          0 :   if (!tree_fits_uhwi_p (TYPE_SIZE (base)))
     609                 :            :     {
     610                 :          0 :       HSA_SORRY_ATV (EXPR_LOCATION (type),
     611                 :            :                      "support for HSA does not implement huge or "
     612                 :            :                      "variable-sized type %qT", type);
     613                 :          0 :       return res;
     614                 :            :     }
     615                 :            : 
     616                 :          0 :   bsize = tree_to_uhwi (TYPE_SIZE (base));
     617                 :          0 :   unsigned byte_size = bsize / BITS_PER_UNIT;
     618                 :          0 :   if (INTEGRAL_TYPE_P (base))
     619                 :          0 :     res = get_integer_type_by_bytes (byte_size, !TYPE_UNSIGNED (base));
     620                 :          0 :   else if (SCALAR_FLOAT_TYPE_P (base))
     621                 :            :     {
     622                 :          0 :       switch (bsize)
     623                 :            :         {
     624                 :            :         case 16:
     625                 :            :           res = BRIG_TYPE_F16;
     626                 :            :           break;
     627                 :            :         case 32:
     628                 :            :           res = BRIG_TYPE_F32;
     629                 :            :           break;
     630                 :            :         case 64:
     631                 :            :           res = BRIG_TYPE_F64;
     632                 :            :           break;
     633                 :            :         default:
     634                 :            :           break;
     635                 :            :         }
     636                 :            :     }
     637                 :            : 
     638                 :          0 :   if (res == BRIG_TYPE_NONE)
     639                 :            :     {
     640                 :          0 :       HSA_SORRY_ATV (EXPR_LOCATION (type),
     641                 :            :                      "support for HSA does not implement type %qT", type);
     642                 :          0 :       return res;
     643                 :            :     }
     644                 :            : 
     645                 :          0 :   if (TREE_CODE (type) == VECTOR_TYPE)
     646                 :            :     {
     647                 :          0 :       HOST_WIDE_INT tsize = tree_to_uhwi (TYPE_SIZE (type));
     648                 :            : 
     649                 :          0 :       if (bsize == tsize)
     650                 :            :         {
     651                 :          0 :           HSA_SORRY_ATV (EXPR_LOCATION (type),
     652                 :            :                          "support for HSA does not implement a vector type "
     653                 :            :                          "where a type and unit size are equal: %qT", type);
     654                 :          0 :           return res;
     655                 :            :         }
     656                 :            : 
     657                 :          0 :       switch (tsize)
     658                 :            :         {
     659                 :          0 :         case 32:
     660                 :          0 :           res |= BRIG_TYPE_PACK_32;
     661                 :          0 :           break;
     662                 :          0 :         case 64:
     663                 :          0 :           res |= BRIG_TYPE_PACK_64;
     664                 :          0 :           break;
     665                 :          0 :         case 128:
     666                 :          0 :           res |= BRIG_TYPE_PACK_128;
     667                 :          0 :           break;
     668                 :          0 :         default:
     669                 :          0 :           HSA_SORRY_ATV (EXPR_LOCATION (type),
     670                 :            :                          "support for HSA does not implement type %qT", type);
     671                 :            :         }
     672                 :            :     }
     673                 :            : 
     674                 :          0 :   if (min32int)
     675                 :            :     /* Registers/immediate operands can only be 32bit or more except for
     676                 :            :        f16.  */
     677                 :          0 :     res = hsa_extend_inttype_to_32bit (res);
     678                 :            : 
     679                 :          0 :   if (TREE_CODE (type) == COMPLEX_TYPE)
     680                 :            :     {
     681                 :          0 :       unsigned bsize = 2 * hsa_type_bit_size (res);
     682                 :          0 :       res = hsa_bittype_for_bitsize (bsize);
     683                 :            :     }
     684                 :            : 
     685                 :            :   return res;
     686                 :            : }
     687                 :            : 
     688                 :            : /* Returns the BRIG type we need to load/store entities of TYPE.  */
     689                 :            : 
     690                 :            : static BrigType16_t
     691                 :          0 : mem_type_for_type (BrigType16_t type)
     692                 :            : {
     693                 :            :   /* HSA has non-intuitive constraints on load/store types.  If it's
     694                 :            :      a bit-type it _must_ be B128, if it's not a bit-type it must be
     695                 :            :      64bit max.  So for loading entities of 128 bits (e.g. vectors)
     696                 :            :      we have to use B128, while for loading the rest we have to use the
     697                 :            :      input type (??? or maybe also flattened to a equally sized non-vector
     698                 :            :      unsigned type?).  */
     699                 :          0 :   if ((type & BRIG_TYPE_PACK_MASK) == BRIG_TYPE_PACK_128)
     700                 :            :     return BRIG_TYPE_B128;
     701                 :          0 :   else if (hsa_btype_p (type) || hsa_type_packed_p (type))
     702                 :            :     {
     703                 :          0 :       unsigned bitsize = hsa_type_bit_size (type);
     704                 :          0 :       if (bitsize < 128)
     705                 :          0 :         return hsa_uint_for_bitsize (bitsize);
     706                 :            :       else
     707                 :          0 :         return hsa_bittype_for_bitsize (bitsize);
     708                 :            :     }
     709                 :            :   return type;
     710                 :            : }
     711                 :            : 
     712                 :            : /* Return HSA type for tree TYPE.  If it cannot fit into BrigType16_t, some
     713                 :            :    kind of array will be generated, setting DIM appropriately.  Otherwise, it
     714                 :            :    will be set to zero.  */
     715                 :            : 
     716                 :            : static BrigType16_t
     717                 :          0 : hsa_type_for_tree_type (const_tree type, unsigned HOST_WIDE_INT *dim_p = NULL,
     718                 :            :                         bool min32int = false)
     719                 :            : {
     720                 :          0 :   gcc_checking_assert (TYPE_P (type));
     721                 :          0 :   if (!tree_fits_uhwi_p (TYPE_SIZE_UNIT (type)))
     722                 :            :     {
     723                 :          0 :       HSA_SORRY_ATV (EXPR_LOCATION (type), "support for HSA does not "
     724                 :            :                      "implement huge or variable-sized type %qT", type);
     725                 :          0 :       return BRIG_TYPE_NONE;
     726                 :            :     }
     727                 :            : 
     728                 :          0 :   if (RECORD_OR_UNION_TYPE_P (type))
     729                 :            :     {
     730                 :          0 :       if (dim_p)
     731                 :          0 :         *dim_p = tree_to_uhwi (TYPE_SIZE_UNIT (type));
     732                 :          0 :       return BRIG_TYPE_U8 | BRIG_TYPE_ARRAY;
     733                 :            :     }
     734                 :            : 
     735                 :          0 :   if (TREE_CODE (type) == ARRAY_TYPE)
     736                 :            :     {
     737                 :            :       /* We try to be nice and use the real base-type when this is an array of
     738                 :            :          scalars and only resort to an array of bytes if the type is more
     739                 :            :          complex.  */
     740                 :            : 
     741                 :            :       unsigned HOST_WIDE_INT dim = 1;
     742                 :            : 
     743                 :          0 :       while (TREE_CODE (type) == ARRAY_TYPE)
     744                 :            :         {
     745                 :          0 :           tree domain = TYPE_DOMAIN (type);
     746                 :          0 :           if (!TYPE_MIN_VALUE (domain)
     747                 :          0 :               || !TYPE_MAX_VALUE (domain)
     748                 :          0 :               || !tree_fits_shwi_p (TYPE_MIN_VALUE (domain))
     749                 :          0 :               || !tree_fits_shwi_p (TYPE_MAX_VALUE (domain)))
     750                 :            :             {
     751                 :          0 :               HSA_SORRY_ATV (EXPR_LOCATION (type),
     752                 :            :                              "support for HSA does not implement array "
     753                 :            :                              "%qT with unknown bounds", type);
     754                 :          0 :               return BRIG_TYPE_NONE;
     755                 :            :             }
     756                 :          0 :           HOST_WIDE_INT min = tree_to_shwi (TYPE_MIN_VALUE (domain));
     757                 :          0 :           HOST_WIDE_INT max = tree_to_shwi (TYPE_MAX_VALUE (domain));
     758                 :          0 :           dim = dim * (unsigned HOST_WIDE_INT) (max - min + 1);
     759                 :          0 :           type = TREE_TYPE (type);
     760                 :            :         }
     761                 :            : 
     762                 :          0 :       BrigType16_t res;
     763                 :          0 :       if (RECORD_OR_UNION_TYPE_P (type))
     764                 :            :         {
     765                 :          0 :           dim = dim * tree_to_uhwi (TYPE_SIZE_UNIT (type));
     766                 :          0 :           res = BRIG_TYPE_U8;
     767                 :            :         }
     768                 :            :       else
     769                 :          0 :         res = hsa_type_for_scalar_tree_type (type, false);
     770                 :            : 
     771                 :          0 :       if (dim_p)
     772                 :          0 :         *dim_p = dim;
     773                 :          0 :       return res | BRIG_TYPE_ARRAY;
     774                 :            :     }
     775                 :            : 
     776                 :            :   /* Scalar case: */
     777                 :          0 :   if (dim_p)
     778                 :          0 :     *dim_p = 0;
     779                 :            : 
     780                 :          0 :   return hsa_type_for_scalar_tree_type (type, min32int);
     781                 :            : }
     782                 :            : 
     783                 :            : /* Returns true if converting from STYPE into DTYPE needs the _CVT
     784                 :            :    opcode.  If false a normal _MOV is enough.  */
     785                 :            : 
     786                 :            : static bool
     787                 :          0 : hsa_needs_cvt (BrigType16_t dtype, BrigType16_t stype)
     788                 :            : {
     789                 :          0 :   if (hsa_btype_p (dtype))
     790                 :            :     return false;
     791                 :            : 
     792                 :            :   /* float <-> int conversions are real converts.  */
     793                 :          0 :   if (hsa_type_float_p (dtype) != hsa_type_float_p (stype))
     794                 :            :     return true;
     795                 :            :   /* When both types have different size, then we need CVT as well.  */
     796                 :          0 :   if (hsa_type_bit_size (dtype) != hsa_type_bit_size (stype))
     797                 :          0 :     return true;
     798                 :            :   return false;
     799                 :            : }
     800                 :            : 
     801                 :            : /* Return declaration name if it exists or create one from UID if it does not.
     802                 :            :    If DECL is a local variable, make UID part of its name.  */
     803                 :            : 
     804                 :            : const char *
     805                 :          0 : hsa_get_declaration_name (tree decl)
     806                 :            : {
     807                 :          0 :   if (!DECL_NAME (decl))
     808                 :            :     {
     809                 :          0 :       char buf[64];
     810                 :          0 :       snprintf (buf, 64, "__hsa_anon_%u", DECL_UID (decl));
     811                 :          0 :       size_t len = strlen (buf);
     812                 :          0 :       char *copy = (char *) obstack_alloc (&hsa_obstack, len + 1);
     813                 :          0 :       memcpy (copy, buf, len + 1);
     814                 :          0 :       return copy;
     815                 :            :     }
     816                 :            : 
     817                 :          0 :   tree name_tree;
     818                 :          0 :   if (TREE_CODE (decl) == FUNCTION_DECL
     819                 :          0 :       || (TREE_CODE (decl) == VAR_DECL && is_global_var (decl)))
     820                 :          0 :     name_tree = DECL_ASSEMBLER_NAME (decl);
     821                 :            :   else
     822                 :          0 :     name_tree = DECL_NAME (decl);
     823                 :            : 
     824                 :          0 :   const char *name = IDENTIFIER_POINTER (name_tree);
     825                 :            :   /* User-defined assembly names have prepended asterisk symbol.  */
     826                 :          0 :   if (name[0] == '*')
     827                 :          0 :     name++;
     828                 :            : 
     829                 :          0 :   if ((TREE_CODE (decl) == VAR_DECL)
     830                 :          0 :       && decl_function_context (decl))
     831                 :            :     {
     832                 :          0 :       size_t len = strlen (name);
     833                 :          0 :       char *buf = (char *) alloca (len + 32);
     834                 :          0 :       snprintf (buf, len + 32, "%s_%u", name, DECL_UID (decl));
     835                 :          0 :       len = strlen (buf);
     836                 :          0 :       char *copy = (char *) obstack_alloc (&hsa_obstack, len + 1);
     837                 :          0 :       memcpy (copy, buf, len + 1);
     838                 :          0 :       return copy;
     839                 :            :     }
     840                 :            :   else
     841                 :          0 :     return name;
     842                 :            : }
     843                 :            : 
     844                 :            : /* Lookup or create the associated hsa_symbol structure with a given VAR_DECL
     845                 :            :    or lookup the hsa_structure corresponding to a PARM_DECL.  */
     846                 :            : 
     847                 :            : static hsa_symbol *
     848                 :          0 : get_symbol_for_decl (tree decl)
     849                 :            : {
     850                 :          0 :   hsa_symbol **slot;
     851                 :          0 :   hsa_symbol dummy (BRIG_TYPE_NONE, BRIG_SEGMENT_NONE, BRIG_LINKAGE_NONE);
     852                 :            : 
     853                 :          0 :   gcc_assert (TREE_CODE (decl) == PARM_DECL
     854                 :            :               || TREE_CODE (decl) == RESULT_DECL
     855                 :            :               || TREE_CODE (decl) == VAR_DECL
     856                 :            :               || TREE_CODE (decl) == CONST_DECL);
     857                 :            : 
     858                 :          0 :   dummy.m_decl = decl;
     859                 :            : 
     860                 :          0 :   bool is_in_global_vars = ((TREE_CODE (decl) == VAR_DECL)
     861                 :          0 :                             && !decl_function_context (decl));
     862                 :            : 
     863                 :          0 :   if (is_in_global_vars)
     864                 :          0 :     slot = hsa_global_variable_symbols->find_slot (&dummy, INSERT);
     865                 :            :   else
     866                 :          0 :     slot = hsa_cfun->m_local_symbols->find_slot (&dummy, INSERT);
     867                 :            : 
     868                 :          0 :   gcc_checking_assert (slot);
     869                 :          0 :   if (*slot)
     870                 :            :     {
     871                 :          0 :       hsa_symbol *sym = (*slot);
     872                 :            : 
     873                 :            :       /* If the symbol is problematic, mark current function also as
     874                 :            :          problematic.  */
     875                 :          0 :       if (sym->m_seen_error)
     876                 :          0 :         hsa_fail_cfun ();
     877                 :            : 
     878                 :            :       /* PR hsa/70234: If a global variable was marked to be emitted,
     879                 :            :          but HSAIL generation of a function using the variable fails,
     880                 :            :          we should retry to emit the variable in context of a different
     881                 :            :          function.
     882                 :            : 
     883                 :            :          Iterate elements whether a symbol is already in m_global_symbols
     884                 :            :          of not.  */
     885                 :          0 :         if (is_in_global_vars && !sym->m_emitted_to_brig)
     886                 :            :           {
     887                 :          0 :             for (unsigned i = 0; i < hsa_cfun->m_global_symbols.length (); i++)
     888                 :          0 :               if (hsa_cfun->m_global_symbols[i] == sym)
     889                 :          0 :                 return *slot;
     890                 :          0 :             hsa_cfun->m_global_symbols.safe_push (sym);
     891                 :            :           }
     892                 :            : 
     893                 :          0 :       return *slot;
     894                 :            :     }
     895                 :            :   else
     896                 :            :     {
     897                 :          0 :       hsa_symbol *sym;
     898                 :            :       /* PARM_DECLs and RESULT_DECL should be already in m_local_symbols.  */
     899                 :          0 :       gcc_assert (TREE_CODE (decl) == VAR_DECL
     900                 :            :                   || TREE_CODE (decl) == CONST_DECL);
     901                 :          0 :       BrigAlignment8_t align = hsa_object_alignment (decl);
     902                 :            : 
     903                 :          0 :       if (is_in_global_vars)
     904                 :            :         {
     905                 :          0 :           gcc_checking_assert (TREE_CODE (decl) != CONST_DECL);
     906                 :          0 :           sym = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_GLOBAL,
     907                 :            :                                 BRIG_LINKAGE_PROGRAM, true,
     908                 :          0 :                                 BRIG_ALLOCATION_PROGRAM, align);
     909                 :          0 :           hsa_cfun->m_global_symbols.safe_push (sym);
     910                 :          0 :           sym->fillup_for_decl (decl);
     911                 :          0 :           if (sym->m_align > align)
     912                 :            :             {
     913                 :          0 :               sym->m_seen_error = true;
     914                 :          0 :               HSA_SORRY_ATV (EXPR_LOCATION (decl),
     915                 :            :                              "HSA specification requires that %E is at least "
     916                 :            :                              "naturally aligned", decl);
     917                 :            :             }
     918                 :            :         }
     919                 :            :       else
     920                 :            :         {
     921                 :            :           /* As generation of efficient memory copy instructions relies
     922                 :            :              on alignment greater or equal to 8 bytes,
     923                 :            :              we need to increase alignment of all aggregate types.. */
     924                 :          0 :           if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
     925                 :          0 :             align = MAX ((BrigAlignment8_t) BRIG_ALIGNMENT_8, align);
     926                 :            : 
     927                 :          0 :           BrigAllocation allocation = BRIG_ALLOCATION_AUTOMATIC;
     928                 :          0 :           BrigSegment8_t segment;
     929                 :          0 :           if (TREE_CODE (decl) == CONST_DECL)
     930                 :            :             {
     931                 :            :               segment = BRIG_SEGMENT_READONLY;
     932                 :            :               allocation = BRIG_ALLOCATION_AGENT;
     933                 :            :             }
     934                 :          0 :           else if (lookup_attribute ("hsa_group_segment",
     935                 :          0 :                                      DECL_ATTRIBUTES (decl)))
     936                 :            :             segment = BRIG_SEGMENT_GROUP;
     937                 :          0 :           else if (TREE_STATIC (decl))
     938                 :            :             {
     939                 :            :               segment = BRIG_SEGMENT_GLOBAL;
     940                 :            :               allocation = BRIG_ALLOCATION_PROGRAM;
     941                 :            :             }
     942                 :          0 :           else if (lookup_attribute ("hsa_global_segment",
     943                 :          0 :                                      DECL_ATTRIBUTES (decl)))
     944                 :            :             segment = BRIG_SEGMENT_GLOBAL;
     945                 :            :           else
     946                 :          0 :             segment = BRIG_SEGMENT_PRIVATE;
     947                 :            : 
     948                 :          0 :           sym = new hsa_symbol (BRIG_TYPE_NONE, segment, BRIG_LINKAGE_FUNCTION,
     949                 :          0 :                                 false, allocation, align);
     950                 :          0 :           sym->fillup_for_decl (decl);
     951                 :          0 :           hsa_cfun->m_private_variables.safe_push (sym);
     952                 :            :         }
     953                 :            : 
     954                 :          0 :       sym->m_name = hsa_get_declaration_name (decl);
     955                 :          0 :       *slot = sym;
     956                 :          0 :       return sym;
     957                 :            :     }
     958                 :            : }
     959                 :            : 
     960                 :            : /* For a given HSA function declaration, return a host
     961                 :            :    function declaration.  */
     962                 :            : 
     963                 :            : tree
     964                 :          0 : hsa_get_host_function (tree decl)
     965                 :            : {
     966                 :          0 :   hsa_function_summary *s = hsa_summaries->get (cgraph_node::get_create (decl));
     967                 :          0 :   gcc_assert (s->m_gpu_implementation_p);
     968                 :            : 
     969                 :          0 :   return s->m_bound_function ? s->m_bound_function->decl : NULL;
     970                 :            : }
     971                 :            : 
     972                 :            : /* Return true if function DECL has a host equivalent function.  */
     973                 :            : 
     974                 :            : static char *
     975                 :          0 : get_brig_function_name (tree decl)
     976                 :            : {
     977                 :          0 :   tree d = decl;
     978                 :            : 
     979                 :          0 :   hsa_function_summary *s = hsa_summaries->get (cgraph_node::get_create (d));
     980                 :          0 :   if (s != NULL
     981                 :          0 :       && s->m_gpu_implementation_p
     982                 :          0 :       && s->m_bound_function)
     983                 :          0 :     d = s->m_bound_function->decl;
     984                 :            : 
     985                 :            :   /* IPA split can create a function that has no host equivalent.  */
     986                 :          0 :   if (d == NULL)
     987                 :          0 :     d = decl;
     988                 :            : 
     989                 :          0 :   char *name = xstrdup (hsa_get_declaration_name (d));
     990                 :          0 :   hsa_sanitize_name (name);
     991                 :            : 
     992                 :          0 :   return name;
     993                 :            : }
     994                 :            : 
     995                 :            : /* Create a spill symbol of type TYPE.  */
     996                 :            : 
     997                 :            : hsa_symbol *
     998                 :          0 : hsa_get_spill_symbol (BrigType16_t type)
     999                 :            : {
    1000                 :          0 :   hsa_symbol *sym = new hsa_symbol (type, BRIG_SEGMENT_SPILL,
    1001                 :          0 :                                     BRIG_LINKAGE_FUNCTION);
    1002                 :          0 :   hsa_cfun->m_spill_symbols.safe_push (sym);
    1003                 :          0 :   return sym;
    1004                 :            : }
    1005                 :            : 
    1006                 :            : /* Create a symbol for a read-only string constant.  */
    1007                 :            : hsa_symbol *
    1008                 :          0 : hsa_get_string_cst_symbol (tree string_cst)
    1009                 :            : {
    1010                 :          0 :   gcc_checking_assert (TREE_CODE (string_cst) == STRING_CST);
    1011                 :            : 
    1012                 :          0 :   hsa_symbol **slot = hsa_cfun->m_string_constants_map.get (string_cst);
    1013                 :          0 :   if (slot)
    1014                 :          0 :     return *slot;
    1015                 :            : 
    1016                 :          0 :   hsa_op_immed *cst = new hsa_op_immed (string_cst);
    1017                 :          0 :   hsa_symbol *sym = new hsa_symbol (cst->m_type, BRIG_SEGMENT_GLOBAL,
    1018                 :            :                                     BRIG_LINKAGE_MODULE, true,
    1019                 :          0 :                                     BRIG_ALLOCATION_AGENT);
    1020                 :          0 :   sym->m_cst_value = cst;
    1021                 :          0 :   sym->m_dim = TREE_STRING_LENGTH (string_cst);
    1022                 :          0 :   sym->m_name_number = hsa_cfun->m_global_symbols.length ();
    1023                 :            : 
    1024                 :          0 :   hsa_cfun->m_global_symbols.safe_push (sym);
    1025                 :          0 :   hsa_cfun->m_string_constants_map.put (string_cst, sym);
    1026                 :          0 :   return sym;
    1027                 :            : }
    1028                 :            : 
    1029                 :            : /* Make the type of a MOV instruction larger if mandated by HSAIL rules.  */
    1030                 :            : 
    1031                 :            : static void
    1032                 :          0 : hsa_fixup_mov_insn_type (hsa_insn_basic *insn)
    1033                 :            : {
    1034                 :          0 :   insn->m_type = hsa_extend_inttype_to_32bit (insn->m_type);
    1035                 :          0 :   if (insn->m_type == BRIG_TYPE_B8 || insn->m_type == BRIG_TYPE_B16)
    1036                 :          0 :     insn->m_type = BRIG_TYPE_B32;
    1037                 :          0 : }
    1038                 :            : 
    1039                 :            : /* Constructor of the ancestor of all operands.  K is BRIG kind that identified
    1040                 :            :    what the operator is.  */
    1041                 :            : 
    1042                 :          0 : hsa_op_base::hsa_op_base (BrigKind16_t k)
    1043                 :          0 :   : m_next (NULL), m_brig_op_offset (0), m_kind (k)
    1044                 :            : {
    1045                 :          0 :   hsa_operands.safe_push (this);
    1046                 :          0 : }
    1047                 :            : 
    1048                 :            : /* Constructor of ancestor of all operands which have a type.  K is BRIG kind
    1049                 :            :    that identified what the operator is.  T is the type of the operator.  */
    1050                 :            : 
    1051                 :          0 : hsa_op_with_type::hsa_op_with_type (BrigKind16_t k, BrigType16_t t)
    1052                 :          0 :   : hsa_op_base (k), m_type (t)
    1053                 :            : {
    1054                 :          0 : }
    1055                 :            : 
    1056                 :            : hsa_op_with_type *
    1057                 :          0 : hsa_op_with_type::get_in_type (BrigType16_t dtype, hsa_bb *hbb)
    1058                 :            : {
    1059                 :          0 :   if (m_type == dtype)
    1060                 :            :     return this;
    1061                 :            : 
    1062                 :          0 :   hsa_op_reg *dest;
    1063                 :            : 
    1064                 :          0 :   if (hsa_needs_cvt (dtype, m_type))
    1065                 :            :     {
    1066                 :          0 :       dest = new hsa_op_reg (dtype);
    1067                 :          0 :       hbb->append_insn (new hsa_insn_cvt (dest, this));
    1068                 :            :     }
    1069                 :          0 :   else if (is_a <hsa_op_reg *> (this))
    1070                 :            :     {
    1071                 :            :       /* In the end, HSA registers do not really have types, only sizes, so if
    1072                 :            :          the sizes match, we can use the register directly.  */
    1073                 :          0 :       gcc_checking_assert (hsa_type_bit_size (dtype)
    1074                 :            :                            == hsa_type_bit_size (m_type));
    1075                 :            :       return this;
    1076                 :            :     }
    1077                 :            :   else
    1078                 :            :     {
    1079                 :          0 :       dest = new hsa_op_reg (m_type);
    1080                 :            : 
    1081                 :          0 :       hsa_insn_basic *mov = new hsa_insn_basic (2, BRIG_OPCODE_MOV,
    1082                 :          0 :                                                 dest->m_type, dest, this);
    1083                 :          0 :       hsa_fixup_mov_insn_type (mov);
    1084                 :          0 :       hbb->append_insn (mov);
    1085                 :            :       /* We cannot simply for instance: 'mov_u32 $_3, 48 (s32)' because
    1086                 :            :          type of the operand must be same as type of the instruction.  */
    1087                 :          0 :       dest->m_type = dtype;
    1088                 :            :     }
    1089                 :            : 
    1090                 :            :   return dest;
    1091                 :            : }
    1092                 :            : 
    1093                 :            : /* If this operand has integer type smaller than 32 bits, extend it to 32 bits,
    1094                 :            :    adding instructions to HBB if needed.  */
    1095                 :            : 
    1096                 :            : hsa_op_with_type *
    1097                 :          0 : hsa_op_with_type::extend_int_to_32bit (hsa_bb *hbb)
    1098                 :            : {
    1099                 :          0 :   if (m_type == BRIG_TYPE_U8 || m_type == BRIG_TYPE_U16)
    1100                 :          0 :     return get_in_type (BRIG_TYPE_U32, hbb);
    1101                 :          0 :   else if (m_type == BRIG_TYPE_S8 || m_type == BRIG_TYPE_S16)
    1102                 :          0 :     return get_in_type (BRIG_TYPE_S32, hbb);
    1103                 :            :   else
    1104                 :            :     return this;
    1105                 :            : }
    1106                 :            : 
    1107                 :            : /* Constructor of class representing HSA immediate values.  TREE_VAL is the
    1108                 :            :    tree representation of the immediate value.  If min32int is true,
    1109                 :            :    always expand integer types to one that has at least 32 bits.  */
    1110                 :            : 
    1111                 :          0 : hsa_op_immed::hsa_op_immed (tree tree_val, bool min32int)
    1112                 :            :   : hsa_op_with_type (BRIG_KIND_OPERAND_CONSTANT_BYTES,
    1113                 :          0 :                       hsa_type_for_tree_type (TREE_TYPE (tree_val), NULL,
    1114                 :          0 :                                               min32int))
    1115                 :            : {
    1116                 :          0 :   if (hsa_seen_error ())
    1117                 :            :     return;
    1118                 :            : 
    1119                 :          0 :   gcc_checking_assert ((is_gimple_min_invariant (tree_val)
    1120                 :            :                        && (!POINTER_TYPE_P (TREE_TYPE (tree_val))
    1121                 :            :                            || TREE_CODE (tree_val) == INTEGER_CST))
    1122                 :            :                        || TREE_CODE (tree_val) == CONSTRUCTOR);
    1123                 :          0 :   m_tree_value = tree_val;
    1124                 :            : 
    1125                 :            :   /* Verify that all elements of a constructor are constants.  */
    1126                 :          0 :   if (TREE_CODE (m_tree_value) == CONSTRUCTOR)
    1127                 :          0 :     for (unsigned i = 0; i < CONSTRUCTOR_NELTS (m_tree_value); i++)
    1128                 :            :       {
    1129                 :          0 :         tree v = CONSTRUCTOR_ELT (m_tree_value, i)->value;
    1130                 :          0 :         if (!CONSTANT_CLASS_P (v))
    1131                 :            :           {
    1132                 :          0 :             HSA_SORRY_AT (EXPR_LOCATION (tree_val),
    1133                 :            :                           "HSA ctor should have only constants");
    1134                 :          0 :             return;
    1135                 :            :           }
    1136                 :            :       }
    1137                 :            : }
    1138                 :            : 
    1139                 :            : /* Constructor of class representing HSA immediate values.  INTEGER_VALUE is the
    1140                 :            :    integer representation of the immediate value.  TYPE is BRIG type.  */
    1141                 :            : 
    1142                 :          0 : hsa_op_immed::hsa_op_immed (HOST_WIDE_INT integer_value, BrigType16_t type)
    1143                 :            :   : hsa_op_with_type (BRIG_KIND_OPERAND_CONSTANT_BYTES, type),
    1144                 :          0 :     m_tree_value (NULL)
    1145                 :            : {
    1146                 :          0 :   gcc_assert (hsa_type_integer_p (type));
    1147                 :          0 :   m_int_value = integer_value;
    1148                 :          0 : }
    1149                 :            : 
    1150                 :          0 : hsa_op_immed::hsa_op_immed ()
    1151                 :          0 :   : hsa_op_with_type (BRIG_KIND_NONE, BRIG_TYPE_NONE)
    1152                 :            : {
    1153                 :          0 : }
    1154                 :            : 
    1155                 :            : /* New operator to allocate immediate operands from obstack.  */
    1156                 :            : 
    1157                 :            : void *
    1158                 :          0 : hsa_op_immed::operator new (size_t size)
    1159                 :            : {
    1160                 :          0 :   return obstack_alloc (&hsa_obstack, size);
    1161                 :            : }
    1162                 :            : 
    1163                 :            : /* Destructor.  */
    1164                 :            : 
    1165                 :          0 : hsa_op_immed::~hsa_op_immed ()
    1166                 :            : {
    1167                 :          0 : }
    1168                 :            : 
    1169                 :            : /* Change type of the immediate value to T.  */
    1170                 :            : 
    1171                 :            : void
    1172                 :          0 : hsa_op_immed::set_type (BrigType16_t t)
    1173                 :            : {
    1174                 :          0 :   m_type = t;
    1175                 :          0 : }
    1176                 :            : 
    1177                 :            : /* Constructor of class representing HSA registers and pseudo-registers.  T is
    1178                 :            :    the BRIG type of the new register.  */
    1179                 :            : 
    1180                 :          0 : hsa_op_reg::hsa_op_reg (BrigType16_t t)
    1181                 :            :   : hsa_op_with_type (BRIG_KIND_OPERAND_REGISTER, t), m_gimple_ssa (NULL_TREE),
    1182                 :          0 :     m_def_insn (NULL), m_spill_sym (NULL), m_order (hsa_cfun->m_reg_count++),
    1183                 :          0 :     m_lr_begin (0), m_lr_end (0), m_reg_class (0), m_hard_num (0)
    1184                 :            : {
    1185                 :          0 : }
    1186                 :            : 
    1187                 :            : /* New operator to allocate a register from obstack.  */
    1188                 :            : 
    1189                 :            : void *
    1190                 :          0 : hsa_op_reg::operator new (size_t size)
    1191                 :            : {
    1192                 :          0 :   return obstack_alloc (&hsa_obstack, size);
    1193                 :            : }
    1194                 :            : 
    1195                 :            : /* Verify register operand.  */
    1196                 :            : 
    1197                 :            : void
    1198                 :          0 : hsa_op_reg::verify_ssa ()
    1199                 :            : {
    1200                 :            :   /* Verify that each HSA register has a definition assigned.
    1201                 :            :      Exceptions are VAR_DECL and PARM_DECL that are a default
    1202                 :            :      definition.  */
    1203                 :          0 :   gcc_checking_assert (m_def_insn
    1204                 :            :                        || (m_gimple_ssa != NULL
    1205                 :            :                            && (!SSA_NAME_VAR (m_gimple_ssa)
    1206                 :            :                                || (TREE_CODE (SSA_NAME_VAR (m_gimple_ssa))
    1207                 :            :                                    != PARM_DECL))
    1208                 :            :                            && SSA_NAME_IS_DEFAULT_DEF (m_gimple_ssa)));
    1209                 :            : 
    1210                 :            :   /* Verify that every use of the register is really present
    1211                 :            :      in an instruction.  */
    1212                 :          0 :   for (unsigned i = 0; i < m_uses.length (); i++)
    1213                 :            :     {
    1214                 :          0 :       hsa_insn_basic *use = m_uses[i];
    1215                 :            : 
    1216                 :          0 :       bool is_visited = false;
    1217                 :          0 :       for (unsigned j = 0; j < use->operand_count (); j++)
    1218                 :            :         {
    1219                 :          0 :           hsa_op_base *u = use->get_op (j);
    1220                 :          0 :           hsa_op_address *addr; addr = dyn_cast <hsa_op_address *> (u);
    1221                 :          0 :           if (addr && addr->m_reg)
    1222                 :          0 :             u = addr->m_reg;
    1223                 :            : 
    1224                 :          0 :           if (u == this)
    1225                 :            :             {
    1226                 :          0 :               bool r = !addr && use->op_output_p (j);
    1227                 :            : 
    1228                 :          0 :               if (r)
    1229                 :            :                 {
    1230                 :          0 :                   error ("HSA SSA name defined by instruction that is supposed "
    1231                 :            :                          "to be using it");
    1232                 :          0 :                   debug_hsa_operand (this);
    1233                 :          0 :                   debug_hsa_insn (use);
    1234                 :          0 :                   internal_error ("HSA SSA verification failed");
    1235                 :            :                 }
    1236                 :            : 
    1237                 :            :               is_visited = true;
    1238                 :            :             }
    1239                 :            :         }
    1240                 :            : 
    1241                 :          0 :       if (!is_visited)
    1242                 :            :         {
    1243                 :          0 :           error ("HSA SSA name not among operands of instruction that is "
    1244                 :            :                  "supposed to use it");
    1245                 :          0 :           debug_hsa_operand (this);
    1246                 :          0 :           debug_hsa_insn (use);
    1247                 :          0 :           internal_error ("HSA SSA verification failed");
    1248                 :            :         }
    1249                 :            :     }
    1250                 :          0 : }
    1251                 :            : 
    1252                 :          0 : hsa_op_address::hsa_op_address (hsa_symbol *sym, hsa_op_reg *r,
    1253                 :          0 :                                 HOST_WIDE_INT offset)
    1254                 :            :   : hsa_op_base (BRIG_KIND_OPERAND_ADDRESS), m_symbol (sym), m_reg (r),
    1255                 :          0 :     m_imm_offset (offset)
    1256                 :            : {
    1257                 :          0 : }
    1258                 :            : 
    1259                 :          0 : hsa_op_address::hsa_op_address (hsa_symbol *sym, HOST_WIDE_INT offset)
    1260                 :            :   : hsa_op_base (BRIG_KIND_OPERAND_ADDRESS), m_symbol (sym), m_reg (NULL),
    1261                 :          0 :     m_imm_offset (offset)
    1262                 :            : {
    1263                 :          0 : }
    1264                 :            : 
    1265                 :          0 : hsa_op_address::hsa_op_address (hsa_op_reg *r, HOST_WIDE_INT offset)
    1266                 :            :   : hsa_op_base (BRIG_KIND_OPERAND_ADDRESS), m_symbol (NULL), m_reg (r),
    1267                 :          0 :     m_imm_offset (offset)
    1268                 :            : {
    1269                 :          0 : }
    1270                 :            : 
    1271                 :            : /* New operator to allocate address operands from obstack.  */
    1272                 :            : 
    1273                 :            : void *
    1274                 :          0 : hsa_op_address::operator new (size_t size)
    1275                 :            : {
    1276                 :          0 :   return obstack_alloc (&hsa_obstack, size);
    1277                 :            : }
    1278                 :            : 
    1279                 :            : /* Constructor of an operand referring to HSAIL code.  */
    1280                 :            : 
    1281                 :          0 : hsa_op_code_ref::hsa_op_code_ref () : hsa_op_base (BRIG_KIND_OPERAND_CODE_REF),
    1282                 :          0 :   m_directive_offset (0)
    1283                 :            : {
    1284                 :          0 : }
    1285                 :            : 
    1286                 :            : /* Constructor of an operand representing a code list.  Set it up so that it
    1287                 :            :    can contain ELEMENTS number of elements.  */
    1288                 :            : 
    1289                 :          0 : hsa_op_code_list::hsa_op_code_list (unsigned elements)
    1290                 :          0 :   : hsa_op_base (BRIG_KIND_OPERAND_CODE_LIST)
    1291                 :            : {
    1292                 :          0 :   m_offsets.create (1);
    1293                 :          0 :   m_offsets.safe_grow_cleared (elements);
    1294                 :          0 : }
    1295                 :            : 
    1296                 :            : /* New operator to allocate code list operands from obstack.  */
    1297                 :            : 
    1298                 :            : void *
    1299                 :          0 : hsa_op_code_list::operator new (size_t size)
    1300                 :            : {
    1301                 :          0 :   return obstack_alloc (&hsa_obstack, size);
    1302                 :            : }
    1303                 :            : 
    1304                 :            : /* Constructor of an operand representing an operand list.
    1305                 :            :    Set it up so that it can contain ELEMENTS number of elements.  */
    1306                 :            : 
    1307                 :          0 : hsa_op_operand_list::hsa_op_operand_list (unsigned elements)
    1308                 :          0 :   : hsa_op_base (BRIG_KIND_OPERAND_OPERAND_LIST)
    1309                 :            : {
    1310                 :          0 :   m_offsets.create (elements);
    1311                 :          0 :   m_offsets.safe_grow (elements);
    1312                 :          0 : }
    1313                 :            : 
    1314                 :            : /* New operator to allocate operand list operands from obstack.  */
    1315                 :            : 
    1316                 :            : void *
    1317                 :          0 : hsa_op_operand_list::operator new (size_t size)
    1318                 :            : {
    1319                 :          0 :   return obstack_alloc (&hsa_obstack, size);
    1320                 :            : }
    1321                 :            : 
    1322                 :          0 : hsa_op_operand_list::~hsa_op_operand_list ()
    1323                 :            : {
    1324                 :          0 :   m_offsets.release ();
    1325                 :          0 : }
    1326                 :            : 
    1327                 :            : 
    1328                 :            : hsa_op_reg *
    1329                 :          0 : hsa_function_representation::reg_for_gimple_ssa (tree ssa)
    1330                 :            : {
    1331                 :          0 :   hsa_op_reg *hreg;
    1332                 :            : 
    1333                 :          0 :   gcc_checking_assert (TREE_CODE (ssa) == SSA_NAME);
    1334                 :          0 :   if (m_ssa_map[SSA_NAME_VERSION (ssa)])
    1335                 :          0 :     return m_ssa_map[SSA_NAME_VERSION (ssa)];
    1336                 :            : 
    1337                 :          0 :   hreg = new hsa_op_reg (hsa_type_for_scalar_tree_type (TREE_TYPE (ssa),
    1338                 :          0 :                                                         false));
    1339                 :          0 :   hreg->m_gimple_ssa = ssa;
    1340                 :          0 :   m_ssa_map[SSA_NAME_VERSION (ssa)] = hreg;
    1341                 :            : 
    1342                 :          0 :   return hreg;
    1343                 :            : }
    1344                 :            : 
    1345                 :            : void
    1346                 :          0 : hsa_op_reg::set_definition (hsa_insn_basic *insn)
    1347                 :            : {
    1348                 :          0 :   if (hsa_cfun->m_in_ssa)
    1349                 :            :     {
    1350                 :          0 :       gcc_checking_assert (!m_def_insn);
    1351                 :          0 :       m_def_insn = insn;
    1352                 :            :     }
    1353                 :            :   else
    1354                 :          0 :     m_def_insn = NULL;
    1355                 :          0 : }
    1356                 :            : 
    1357                 :            : /* Constructor of the class which is the bases of all instructions and directly
    1358                 :            :    represents the most basic ones.  NOPS is the number of operands that the
    1359                 :            :    operand vector will contain (and which will be cleared).  OP is the opcode
    1360                 :            :    of the instruction.  This constructor does not set type.  */
    1361                 :            : 
    1362                 :          0 : hsa_insn_basic::hsa_insn_basic (unsigned nops, int opc)
    1363                 :            :   : m_prev (NULL),
    1364                 :            :     m_next (NULL), m_bb (NULL), m_opcode (opc), m_number (0),
    1365                 :          0 :     m_type (BRIG_TYPE_NONE), m_brig_offset (0)
    1366                 :            : {
    1367                 :          0 :   if (nops > 0)
    1368                 :          0 :     m_operands.safe_grow_cleared (nops);
    1369                 :            : 
    1370                 :          0 :   hsa_instructions.safe_push (this);
    1371                 :          0 : }
    1372                 :            : 
    1373                 :            : /* Make OP the operand number INDEX of operands of this instruction.  If OP is a
    1374                 :            :    register or an address containing a register, then either set the definition
    1375                 :            :    of the register to this instruction if it an output operand or add this
    1376                 :            :    instruction to the uses if it is an input one.  */
    1377                 :            : 
    1378                 :            : void
    1379                 :          0 : hsa_insn_basic::set_op (int index, hsa_op_base *op)
    1380                 :            : {
    1381                 :            :   /* Each address operand is always use.  */
    1382                 :          0 :   hsa_op_address *addr = dyn_cast <hsa_op_address *> (op);
    1383                 :          0 :   if (addr && addr->m_reg)
    1384                 :          0 :     addr->m_reg->m_uses.safe_push (this);
    1385                 :            :   else
    1386                 :            :     {
    1387                 :          0 :       hsa_op_reg *reg = dyn_cast <hsa_op_reg *> (op);
    1388                 :          0 :       if (reg)
    1389                 :            :         {
    1390                 :          0 :           if (op_output_p (index))
    1391                 :          0 :             reg->set_definition (this);
    1392                 :            :           else
    1393                 :          0 :             reg->m_uses.safe_push (this);
    1394                 :            :         }
    1395                 :            :     }
    1396                 :            : 
    1397                 :          0 :   m_operands[index] = op;
    1398                 :          0 : }
    1399                 :            : 
    1400                 :            : /* Get INDEX-th operand of the instruction.  */
    1401                 :            : 
    1402                 :            : hsa_op_base *
    1403                 :          0 : hsa_insn_basic::get_op (int index)
    1404                 :            : {
    1405                 :          0 :   return m_operands[index];
    1406                 :            : }
    1407                 :            : 
    1408                 :            : /* Get address of INDEX-th operand of the instruction.  */
    1409                 :            : 
    1410                 :            : hsa_op_base **
    1411                 :          0 : hsa_insn_basic::get_op_addr (int index)
    1412                 :            : {
    1413                 :          0 :   return &m_operands[index];
    1414                 :            : }
    1415                 :            : 
    1416                 :            : /* Get number of operands of the instruction.  */
    1417                 :            : unsigned int
    1418                 :          0 : hsa_insn_basic::operand_count ()
    1419                 :            : {
    1420                 :          0 :   return m_operands.length ();
    1421                 :            : }
    1422                 :            : 
    1423                 :            : /* Constructor of the class which is the bases of all instructions and directly
    1424                 :            :    represents the most basic ones.  NOPS is the number of operands that the
    1425                 :            :    operand vector will contain (and which will be cleared).  OPC is the opcode
    1426                 :            :    of the instruction, T is the type of the instruction.  */
    1427                 :            : 
    1428                 :          0 : hsa_insn_basic::hsa_insn_basic (unsigned nops, int opc, BrigType16_t t,
    1429                 :            :                                 hsa_op_base *arg0, hsa_op_base *arg1,
    1430                 :          0 :                                 hsa_op_base *arg2, hsa_op_base *arg3)
    1431                 :            :  : m_prev (NULL), m_next (NULL), m_bb (NULL), m_opcode (opc),m_number (0),
    1432                 :          0 :    m_type (t),  m_brig_offset (0)
    1433                 :            : {
    1434                 :          0 :   if (nops > 0)
    1435                 :          0 :     m_operands.safe_grow_cleared (nops);
    1436                 :            : 
    1437                 :          0 :   if (arg0 != NULL)
    1438                 :            :     {
    1439                 :          0 :       gcc_checking_assert (nops >= 1);
    1440                 :          0 :       set_op (0, arg0);
    1441                 :            :     }
    1442                 :            : 
    1443                 :          0 :   if (arg1 != NULL)
    1444                 :            :     {
    1445                 :          0 :       gcc_checking_assert (nops >= 2);
    1446                 :          0 :       set_op (1, arg1);
    1447                 :            :     }
    1448                 :            : 
    1449                 :          0 :   if (arg2 != NULL)
    1450                 :            :     {
    1451                 :          0 :       gcc_checking_assert (nops >= 3);
    1452                 :          0 :       set_op (2, arg2);
    1453                 :            :     }
    1454                 :            : 
    1455                 :          0 :   if (arg3 != NULL)
    1456                 :            :     {
    1457                 :          0 :       gcc_checking_assert (nops >= 4);
    1458                 :          0 :       set_op (3, arg3);
    1459                 :            :     }
    1460                 :            : 
    1461                 :          0 :   hsa_instructions.safe_push (this);
    1462                 :          0 : }
    1463                 :            : 
    1464                 :            : /* New operator to allocate basic instruction from obstack.  */
    1465                 :            : 
    1466                 :            : void *
    1467                 :          0 : hsa_insn_basic::operator new (size_t size)
    1468                 :            : {
    1469                 :          0 :   return obstack_alloc (&hsa_obstack, size);
    1470                 :            : }
    1471                 :            : 
    1472                 :            : /* Verify the instruction.  */
    1473                 :            : 
    1474                 :            : void
    1475                 :          0 : hsa_insn_basic::verify ()
    1476                 :            : {
    1477                 :          0 :   hsa_op_address *addr;
    1478                 :          0 :   hsa_op_reg *reg;
    1479                 :            : 
    1480                 :            :   /* Iterate all register operands and verify that the instruction
    1481                 :            :      is set in uses of the register.  */
    1482                 :          0 :   for (unsigned i = 0; i < operand_count (); i++)
    1483                 :            :     {
    1484                 :          0 :       hsa_op_base *use = get_op (i);
    1485                 :            : 
    1486                 :          0 :       if ((addr = dyn_cast <hsa_op_address *> (use)) && addr->m_reg)
    1487                 :            :         {
    1488                 :          0 :           gcc_assert (addr->m_reg->m_def_insn != this);
    1489                 :            :           use = addr->m_reg;
    1490                 :            :         }
    1491                 :            : 
    1492                 :          0 :       if ((reg = dyn_cast <hsa_op_reg *> (use)) && !op_output_p (i))
    1493                 :            :         {
    1494                 :            :           unsigned j;
    1495                 :          0 :           for (j = 0; j < reg->m_uses.length (); j++)
    1496                 :            :             {
    1497                 :          0 :               if (reg->m_uses[j] == this)
    1498                 :            :                 break;
    1499                 :            :             }
    1500                 :            : 
    1501                 :          0 :           if (j == reg->m_uses.length ())
    1502                 :            :             {
    1503                 :          0 :               error ("HSA instruction uses a register but is not among "
    1504                 :            :                      "recorded register uses");
    1505                 :          0 :               debug_hsa_operand (reg);
    1506                 :          0 :               debug_hsa_insn (this);
    1507                 :          0 :               internal_error ("HSA instruction verification failed");
    1508                 :            :             }
    1509                 :            :         }
    1510                 :            :     }
    1511                 :          0 : }
    1512                 :            : 
    1513                 :            : /* Constructor of an instruction representing a PHI node.  NOPS is the number
    1514                 :            :    of operands (equal to the number of predecessors).  */
    1515                 :            : 
    1516                 :          0 : hsa_insn_phi::hsa_insn_phi (unsigned nops, hsa_op_reg *dst)
    1517                 :          0 :   : hsa_insn_basic (nops, HSA_OPCODE_PHI), m_dest (dst)
    1518                 :            : {
    1519                 :          0 :   dst->set_definition (this);
    1520                 :          0 : }
    1521                 :            : 
    1522                 :            : /* Constructor of class representing instructions for control flow and
    1523                 :            :    sychronization,   */
    1524                 :            : 
    1525                 :          0 : hsa_insn_br::hsa_insn_br (unsigned nops, int opc, BrigType16_t t,
    1526                 :            :                           BrigWidth8_t width, hsa_op_base *arg0,
    1527                 :            :                           hsa_op_base *arg1, hsa_op_base *arg2,
    1528                 :          0 :                           hsa_op_base *arg3)
    1529                 :            :   : hsa_insn_basic (nops, opc, t, arg0, arg1, arg2, arg3),
    1530                 :          0 :     m_width (width)
    1531                 :            : {
    1532                 :          0 : }
    1533                 :            : 
    1534                 :            : /* Constructor of class representing instruction for conditional jump, CTRL is
    1535                 :            :    the control register determining whether the jump will be carried out, the
    1536                 :            :    new instruction is automatically added to its uses list.  */
    1537                 :            : 
    1538                 :          0 : hsa_insn_cbr::hsa_insn_cbr (hsa_op_reg *ctrl)
    1539                 :          0 :   : hsa_insn_br (1, BRIG_OPCODE_CBR, BRIG_TYPE_B1, BRIG_WIDTH_1, ctrl)
    1540                 :            : {
    1541                 :          0 : }
    1542                 :            : 
    1543                 :            : /* Constructor of class representing instruction for switch jump, CTRL is
    1544                 :            :    the index register.  */
    1545                 :            : 
    1546                 :          0 : hsa_insn_sbr::hsa_insn_sbr (hsa_op_reg *index, unsigned jump_count)
    1547                 :            :   : hsa_insn_basic (1, BRIG_OPCODE_SBR, BRIG_TYPE_B1, index),
    1548                 :            :     m_width (BRIG_WIDTH_1), m_jump_table (vNULL),
    1549                 :          0 :     m_label_code_list (new hsa_op_code_list (jump_count))
    1550                 :            : {
    1551                 :          0 : }
    1552                 :            : 
    1553                 :            : /* Replace all occurrences of OLD_BB with NEW_BB in the statements
    1554                 :            :    jump table.  */
    1555                 :            : 
    1556                 :            : void
    1557                 :          0 : hsa_insn_sbr::replace_all_labels (basic_block old_bb, basic_block new_bb)
    1558                 :            : {
    1559                 :          0 :   for (unsigned i = 0; i < m_jump_table.length (); i++)
    1560                 :          0 :     if (m_jump_table[i] == old_bb)
    1561                 :          0 :       m_jump_table[i] = new_bb;
    1562                 :          0 : }
    1563                 :            : 
    1564                 :          0 : hsa_insn_sbr::~hsa_insn_sbr ()
    1565                 :            : {
    1566                 :          0 :   m_jump_table.release ();
    1567                 :          0 : }
    1568                 :            : 
    1569                 :            : /* Constructor of comparison instruction.  CMP is the comparison operation and T
    1570                 :            :    is the result type.  */
    1571                 :            : 
    1572                 :          0 : hsa_insn_cmp::hsa_insn_cmp (BrigCompareOperation8_t cmp, BrigType16_t t,
    1573                 :            :                             hsa_op_base *arg0, hsa_op_base *arg1,
    1574                 :          0 :                             hsa_op_base *arg2)
    1575                 :          0 :   : hsa_insn_basic (3 , BRIG_OPCODE_CMP, t, arg0, arg1, arg2), m_compare (cmp)
    1576                 :            : {
    1577                 :          0 : }
    1578                 :            : 
    1579                 :            : /* Constructor of classes representing memory accesses.  OPC is the opcode (must
    1580                 :            :    be BRIG_OPCODE_ST or BRIG_OPCODE_LD) and T is the type.  The instruction
    1581                 :            :    operands are provided as ARG0 and ARG1.  */
    1582                 :            : 
    1583                 :          0 : hsa_insn_mem::hsa_insn_mem (int opc, BrigType16_t t, hsa_op_base *arg0,
    1584                 :          0 :                             hsa_op_base *arg1)
    1585                 :            :   : hsa_insn_basic (2, opc, t, arg0, arg1),
    1586                 :          0 :     m_align (hsa_natural_alignment (t)), m_equiv_class (0)
    1587                 :            : {
    1588                 :          0 :   gcc_checking_assert (opc == BRIG_OPCODE_LD || opc == BRIG_OPCODE_ST);
    1589                 :          0 : }
    1590                 :            : 
    1591                 :            : /* Constructor for descendants allowing different opcodes and number of
    1592                 :            :    operands, it passes its arguments directly to hsa_insn_basic
    1593                 :            :    constructor.  The instruction operands are provided as ARG[0-3].  */
    1594                 :            : 
    1595                 :            : 
    1596                 :          0 : hsa_insn_mem::hsa_insn_mem (unsigned nops, int opc, BrigType16_t t,
    1597                 :            :                             hsa_op_base *arg0, hsa_op_base *arg1,
    1598                 :          0 :                             hsa_op_base *arg2, hsa_op_base *arg3)
    1599                 :            :   : hsa_insn_basic (nops, opc, t, arg0, arg1, arg2, arg3),
    1600                 :          0 :     m_align (hsa_natural_alignment (t)), m_equiv_class (0)
    1601                 :            : {
    1602                 :          0 : }
    1603                 :            : 
    1604                 :            : /* Constructor of class representing atomic instructions.  OPC is the principal
    1605                 :            :    opcode, AOP is the specific atomic operation opcode.  T is the type of the
    1606                 :            :    instruction.  The instruction operands are provided as ARG[0-3].  */
    1607                 :            : 
    1608                 :          0 : hsa_insn_atomic::hsa_insn_atomic (int nops, int opc,
    1609                 :            :                                   enum BrigAtomicOperation aop,
    1610                 :            :                                   BrigType16_t t, BrigMemoryOrder memorder,
    1611                 :            :                                   hsa_op_base *arg0,
    1612                 :            :                                   hsa_op_base *arg1, hsa_op_base *arg2,
    1613                 :          0 :                                   hsa_op_base *arg3)
    1614                 :            :   : hsa_insn_mem (nops, opc, t, arg0, arg1, arg2, arg3), m_atomicop (aop),
    1615                 :            :     m_memoryorder (memorder),
    1616                 :          0 :     m_memoryscope (BRIG_MEMORY_SCOPE_SYSTEM)
    1617                 :            : {
    1618                 :          0 :   gcc_checking_assert (opc == BRIG_OPCODE_ATOMICNORET ||
    1619                 :            :                        opc == BRIG_OPCODE_ATOMIC ||
    1620                 :            :                        opc == BRIG_OPCODE_SIGNAL ||
    1621                 :            :                        opc == BRIG_OPCODE_SIGNALNORET);
    1622                 :          0 : }
    1623                 :            : 
    1624                 :            : /* Constructor of class representing signal instructions.  OPC is the prinicpal
    1625                 :            :    opcode, SOP is the specific signal operation opcode.  T is the type of the
    1626                 :            :    instruction.  The instruction operands are provided as ARG[0-3].  */
    1627                 :            : 
    1628                 :          0 : hsa_insn_signal::hsa_insn_signal (int nops, int opc,
    1629                 :            :                                   enum BrigAtomicOperation sop,
    1630                 :            :                                   BrigType16_t t, BrigMemoryOrder memorder,
    1631                 :            :                                   hsa_op_base *arg0, hsa_op_base *arg1,
    1632                 :          0 :                                   hsa_op_base *arg2, hsa_op_base *arg3)
    1633                 :            :   : hsa_insn_basic (nops, opc, t, arg0, arg1, arg2, arg3),
    1634                 :          0 :     m_memory_order (memorder), m_signalop (sop)
    1635                 :            : {
    1636                 :          0 : }
    1637                 :            : 
    1638                 :            : /* Constructor of class representing segment conversion instructions.  OPC is
    1639                 :            :    the opcode which must be either BRIG_OPCODE_STOF or BRIG_OPCODE_FTOS.  DEST
    1640                 :            :    and SRCT are destination and source types respectively, SEG is the segment
    1641                 :            :    we are converting to or from.  The instruction operands are
    1642                 :            :    provided as ARG0 and ARG1.  */
    1643                 :            : 
    1644                 :          0 : hsa_insn_seg::hsa_insn_seg (int opc, BrigType16_t dest, BrigType16_t srct,
    1645                 :            :                             BrigSegment8_t seg, hsa_op_base *arg0,
    1646                 :          0 :                             hsa_op_base *arg1)
    1647                 :            :   : hsa_insn_basic (2, opc, dest, arg0, arg1), m_src_type (srct),
    1648                 :          0 :     m_segment (seg)
    1649                 :            : {
    1650                 :          0 :   gcc_checking_assert (opc == BRIG_OPCODE_STOF || opc == BRIG_OPCODE_FTOS);
    1651                 :          0 : }
    1652                 :            : 
    1653                 :            : /* Constructor of class representing a call instruction.  CALLEE is the tree
    1654                 :            :    representation of the function being called.  */
    1655                 :            : 
    1656                 :          0 : hsa_insn_call::hsa_insn_call (tree callee)
    1657                 :            :   : hsa_insn_basic (0, BRIG_OPCODE_CALL), m_called_function (callee),
    1658                 :          0 :     m_output_arg (NULL), m_args_code_list (NULL), m_result_code_list (NULL)
    1659                 :            : {
    1660                 :          0 : }
    1661                 :            : 
    1662                 :          0 : hsa_insn_call::hsa_insn_call (hsa_internal_fn *fn)
    1663                 :            :   : hsa_insn_basic (0, BRIG_OPCODE_CALL), m_called_function (NULL),
    1664                 :            :     m_called_internal_fn (fn), m_output_arg (NULL), m_args_code_list (NULL),
    1665                 :          0 :     m_result_code_list (NULL)
    1666                 :            : {
    1667                 :          0 : }
    1668                 :            : 
    1669                 :          0 : hsa_insn_call::~hsa_insn_call ()
    1670                 :            : {
    1671                 :          0 :   for (unsigned i = 0; i < m_input_args.length (); i++)
    1672                 :          0 :     delete m_input_args[i];
    1673                 :            : 
    1674                 :          0 :   delete m_output_arg;
    1675                 :            : 
    1676                 :          0 :   m_input_args.release ();
    1677                 :          0 :   m_input_arg_insns.release ();
    1678                 :          0 : }
    1679                 :            : 
    1680                 :            : /* Constructor of class representing the argument block required to invoke
    1681                 :            :    a call in HSAIL.  */
    1682                 :          0 : hsa_insn_arg_block::hsa_insn_arg_block (BrigKind brig_kind,
    1683                 :          0 :                                         hsa_insn_call * call)
    1684                 :            :   : hsa_insn_basic (0, HSA_OPCODE_ARG_BLOCK), m_kind (brig_kind),
    1685                 :          0 :     m_call_insn (call)
    1686                 :            : {
    1687                 :          0 : }
    1688                 :            : 
    1689                 :          0 : hsa_insn_comment::hsa_insn_comment (const char *s)
    1690                 :          0 :   : hsa_insn_basic (0, BRIG_KIND_DIRECTIVE_COMMENT)
    1691                 :            : {
    1692                 :          0 :   unsigned l = strlen (s);
    1693                 :            : 
    1694                 :            :   /* Append '// ' to the string.  */
    1695                 :          0 :   char *buf = XNEWVEC (char, l + 4);
    1696                 :          0 :   sprintf (buf, "// %s", s);
    1697                 :          0 :   m_comment = buf;
    1698                 :          0 : }
    1699                 :            : 
    1700                 :          0 : hsa_insn_comment::~hsa_insn_comment ()
    1701                 :            : {
    1702                 :          0 :   gcc_checking_assert (m_comment);
    1703                 :          0 :   free (m_comment);
    1704                 :          0 :   m_comment = NULL;
    1705                 :          0 : }
    1706                 :            : 
    1707                 :            : /* Constructor of class representing the queue instruction in HSAIL.  */
    1708                 :            : 
    1709                 :          0 : hsa_insn_queue::hsa_insn_queue (int nops, int opcode, BrigSegment segment,
    1710                 :            :                                 BrigMemoryOrder memory_order,
    1711                 :            :                                 hsa_op_base *arg0, hsa_op_base *arg1,
    1712                 :          0 :                                 hsa_op_base *arg2, hsa_op_base *arg3)
    1713                 :            :   : hsa_insn_basic (nops, opcode, BRIG_TYPE_U64, arg0, arg1, arg2, arg3),
    1714                 :          0 :     m_segment (segment), m_memory_order (memory_order)
    1715                 :            : {
    1716                 :          0 : }
    1717                 :            : 
    1718                 :            : /* Constructor of class representing the source type instruction in HSAIL.  */
    1719                 :            : 
    1720                 :          0 : hsa_insn_srctype::hsa_insn_srctype (int nops, BrigOpcode opcode,
    1721                 :            :                                     BrigType16_t destt, BrigType16_t srct,
    1722                 :            :                                     hsa_op_base *arg0, hsa_op_base *arg1,
    1723                 :          0 :                                     hsa_op_base *arg2 = NULL)
    1724                 :            :   : hsa_insn_basic (nops, opcode, destt, arg0, arg1, arg2),
    1725                 :          0 :     m_source_type (srct)
    1726                 :          0 : {}
    1727                 :            : 
    1728                 :            : /* Constructor of class representing the packed instruction in HSAIL.  */
    1729                 :            : 
    1730                 :          0 : hsa_insn_packed::hsa_insn_packed (int nops, BrigOpcode opcode,
    1731                 :            :                                   BrigType16_t destt, BrigType16_t srct,
    1732                 :            :                                   hsa_op_base *arg0, hsa_op_base *arg1,
    1733                 :          0 :                                   hsa_op_base *arg2)
    1734                 :          0 :   : hsa_insn_srctype (nops, opcode, destt, srct, arg0, arg1, arg2)
    1735                 :            : {
    1736                 :          0 :   m_operand_list = new hsa_op_operand_list (nops - 1);
    1737                 :          0 : }
    1738                 :            : 
    1739                 :            : /* Constructor of class representing the convert instruction in HSAIL.  */
    1740                 :            : 
    1741                 :          0 : hsa_insn_cvt::hsa_insn_cvt (hsa_op_with_type *dest, hsa_op_with_type *src)
    1742                 :          0 :   : hsa_insn_basic (2, BRIG_OPCODE_CVT, dest->m_type, dest, src)
    1743                 :            : {
    1744                 :          0 : }
    1745                 :            : 
    1746                 :            : /* Constructor of class representing the alloca in HSAIL.  */
    1747                 :            : 
    1748                 :          0 : hsa_insn_alloca::hsa_insn_alloca (hsa_op_with_type *dest,
    1749                 :          0 :                                   hsa_op_with_type *size, unsigned alignment)
    1750                 :          0 :   : hsa_insn_basic (2, BRIG_OPCODE_ALLOCA, dest->m_type, dest, size),
    1751                 :          0 :     m_align (BRIG_ALIGNMENT_8)
    1752                 :            : {
    1753                 :          0 :   gcc_assert (dest->m_type == BRIG_TYPE_U32);
    1754                 :          0 :   if (alignment)
    1755                 :          0 :     m_align = hsa_alignment_encoding (alignment);
    1756                 :          0 : }
    1757                 :            : 
    1758                 :            : /* Append an instruction INSN into the basic block.  */
    1759                 :            : 
    1760                 :            : void
    1761                 :          0 : hsa_bb::append_insn (hsa_insn_basic *insn)
    1762                 :            : {
    1763                 :          0 :   gcc_assert (insn->m_opcode != 0 || insn->operand_count () == 0);
    1764                 :          0 :   gcc_assert (!insn->m_bb);
    1765                 :            : 
    1766                 :          0 :   insn->m_bb = m_bb;
    1767                 :          0 :   insn->m_prev = m_last_insn;
    1768                 :          0 :   insn->m_next = NULL;
    1769                 :          0 :   if (m_last_insn)
    1770                 :          0 :     m_last_insn->m_next = insn;
    1771                 :          0 :   m_last_insn = insn;
    1772                 :          0 :   if (!m_first_insn)
    1773                 :          0 :     m_first_insn = insn;
    1774                 :          0 : }
    1775                 :            : 
    1776                 :            : void
    1777                 :          0 : hsa_bb::append_phi (hsa_insn_phi *hphi)
    1778                 :            : {
    1779                 :          0 :   hphi->m_bb = m_bb;
    1780                 :            : 
    1781                 :          0 :   hphi->m_prev = m_last_phi;
    1782                 :          0 :   hphi->m_next = NULL;
    1783                 :          0 :   if (m_last_phi)
    1784                 :          0 :     m_last_phi->m_next = hphi;
    1785                 :          0 :   m_last_phi = hphi;
    1786                 :          0 :   if (!m_first_phi)
    1787                 :          0 :     m_first_phi = hphi;
    1788                 :          0 : }
    1789                 :            : 
    1790                 :            : /* Insert HSA instruction NEW_INSN immediately before an existing instruction
    1791                 :            :    OLD_INSN.  */
    1792                 :            : 
    1793                 :            : static void
    1794                 :          0 : hsa_insert_insn_before (hsa_insn_basic *new_insn, hsa_insn_basic *old_insn)
    1795                 :            : {
    1796                 :          0 :   hsa_bb *hbb = hsa_bb_for_bb (old_insn->m_bb);
    1797                 :            : 
    1798                 :          0 :   if (hbb->m_first_insn == old_insn)
    1799                 :          0 :     hbb->m_first_insn = new_insn;
    1800                 :          0 :   new_insn->m_prev = old_insn->m_prev;
    1801                 :          0 :   new_insn->m_next = old_insn;
    1802                 :          0 :   if (old_insn->m_prev)
    1803                 :          0 :     old_insn->m_prev->m_next = new_insn;
    1804                 :          0 :   old_insn->m_prev = new_insn;
    1805                 :          0 : }
    1806                 :            : 
    1807                 :            : /* Append HSA instruction NEW_INSN immediately after an existing instruction
    1808                 :            :    OLD_INSN.  */
    1809                 :            : 
    1810                 :            : static void
    1811                 :          0 : hsa_append_insn_after (hsa_insn_basic *new_insn, hsa_insn_basic *old_insn)
    1812                 :            : {
    1813                 :          0 :   hsa_bb *hbb = hsa_bb_for_bb (old_insn->m_bb);
    1814                 :            : 
    1815                 :          0 :   if (hbb->m_last_insn == old_insn)
    1816                 :          0 :     hbb->m_last_insn = new_insn;
    1817                 :          0 :   new_insn->m_prev = old_insn;
    1818                 :          0 :   new_insn->m_next = old_insn->m_next;
    1819                 :          0 :   if (old_insn->m_next)
    1820                 :          0 :     old_insn->m_next->m_prev = new_insn;
    1821                 :          0 :   old_insn->m_next = new_insn;
    1822                 :          0 : }
    1823                 :            : 
    1824                 :            : /* Return a register containing the calculated value of EXP which must be an
    1825                 :            :    expression consisting of PLUS_EXPRs, MULT_EXPRs, NOP_EXPRs, SSA_NAMEs and
    1826                 :            :    integer constants as returned by get_inner_reference.
    1827                 :            :    Newly generated HSA instructions will be appended to HBB.
    1828                 :            :    Perform all calculations in ADDRTYPE.  */
    1829                 :            : 
    1830                 :            : static hsa_op_with_type *
    1831                 :          0 : gen_address_calculation (tree exp, hsa_bb *hbb, BrigType16_t addrtype)
    1832                 :            : {
    1833                 :          0 :   int opcode;
    1834                 :            : 
    1835                 :          0 :   if (TREE_CODE (exp) == NOP_EXPR)
    1836                 :          0 :     exp = TREE_OPERAND (exp, 0);
    1837                 :            : 
    1838                 :          0 :   switch (TREE_CODE (exp))
    1839                 :            :     {
    1840                 :          0 :     case SSA_NAME:
    1841                 :          0 :       return hsa_cfun->reg_for_gimple_ssa (exp)->get_in_type (addrtype, hbb);
    1842                 :            : 
    1843                 :          0 :     case INTEGER_CST:
    1844                 :          0 :       {
    1845                 :          0 :         hsa_op_immed *imm = new hsa_op_immed (exp);
    1846                 :          0 :        if (addrtype != imm->m_type)
    1847                 :          0 :          imm->m_type = addrtype;
    1848                 :            :        return imm;
    1849                 :            :       }
    1850                 :            : 
    1851                 :            :     case PLUS_EXPR:
    1852                 :            :       opcode = BRIG_OPCODE_ADD;
    1853                 :            :       break;
    1854                 :            : 
    1855                 :          0 :     case MULT_EXPR:
    1856                 :          0 :       opcode = BRIG_OPCODE_MUL;
    1857                 :          0 :       break;
    1858                 :            : 
    1859                 :          0 :     default:
    1860                 :          0 :       gcc_unreachable ();
    1861                 :            :     }
    1862                 :            : 
    1863                 :          0 :   hsa_op_reg *res = new hsa_op_reg (addrtype);
    1864                 :          0 :   hsa_insn_basic *insn = new hsa_insn_basic (3, opcode, addrtype);
    1865                 :          0 :   insn->set_op (0, res);
    1866                 :            : 
    1867                 :          0 :   hsa_op_with_type *op1 = gen_address_calculation (TREE_OPERAND (exp, 0), hbb,
    1868                 :            :                                                    addrtype);
    1869                 :          0 :   hsa_op_with_type *op2 = gen_address_calculation (TREE_OPERAND (exp, 1), hbb,
    1870                 :            :                                                    addrtype);
    1871                 :          0 :   insn->set_op (1, op1);
    1872                 :          0 :   insn->set_op (2, op2);
    1873                 :            : 
    1874                 :          0 :   hbb->append_insn (insn);
    1875                 :          0 :   return res;
    1876                 :            : }
    1877                 :            : 
    1878                 :            : /* If R1 is NULL, just return R2, otherwise append an instruction adding them
    1879                 :            :    to HBB and return the register holding the result.  */
    1880                 :            : 
    1881                 :            : static hsa_op_reg *
    1882                 :          0 : add_addr_regs_if_needed (hsa_op_reg *r1, hsa_op_reg *r2, hsa_bb *hbb)
    1883                 :            : {
    1884                 :          0 :   gcc_checking_assert (r2);
    1885                 :          0 :   if (!r1)
    1886                 :            :     return r2;
    1887                 :            : 
    1888                 :          0 :   hsa_op_reg *res = new hsa_op_reg (r1->m_type);
    1889                 :          0 :   gcc_assert (!hsa_needs_cvt (r1->m_type, r2->m_type));
    1890                 :          0 :   hsa_insn_basic *insn = new hsa_insn_basic (3, BRIG_OPCODE_ADD, res->m_type);
    1891                 :          0 :   insn->set_op (0, res);
    1892                 :          0 :   insn->set_op (1, r1);
    1893                 :          0 :   insn->set_op (2, r2);
    1894                 :          0 :   hbb->append_insn (insn);
    1895                 :          0 :   return res;
    1896                 :            : }
    1897                 :            : 
    1898                 :            : /* Helper of gen_hsa_addr.  Update *SYMBOL, *ADDRTYPE, *REG and *OFFSET to
    1899                 :            :    reflect BASE which is the first operand of a MEM_REF or a TARGET_MEM_REF.  */
    1900                 :            : 
    1901                 :            : static void
    1902                 :          0 : process_mem_base (tree base, hsa_symbol **symbol, BrigType16_t *addrtype,
    1903                 :            :                   hsa_op_reg **reg, offset_int *offset, hsa_bb *hbb)
    1904                 :            : {
    1905                 :          0 :   if (TREE_CODE (base) == SSA_NAME)
    1906                 :            :     {
    1907                 :          0 :       gcc_assert (!*reg);
    1908                 :          0 :       hsa_op_with_type *ssa
    1909                 :          0 :         = hsa_cfun->reg_for_gimple_ssa (base)->get_in_type (*addrtype, hbb);
    1910                 :          0 :       *reg = dyn_cast <hsa_op_reg *> (ssa);
    1911                 :            :     }
    1912                 :          0 :   else if (TREE_CODE (base) == ADDR_EXPR)
    1913                 :            :     {
    1914                 :          0 :       tree decl = TREE_OPERAND (base, 0);
    1915                 :            : 
    1916                 :          0 :       if (!DECL_P (decl) || TREE_CODE (decl) == FUNCTION_DECL)
    1917                 :            :         {
    1918                 :          0 :           HSA_SORRY_AT (EXPR_LOCATION (base),
    1919                 :            :                         "support for HSA does not implement a memory reference "
    1920                 :            :                         "to a non-declaration type");
    1921                 :          0 :           return;
    1922                 :            :         }
    1923                 :            : 
    1924                 :          0 :       gcc_assert (!*symbol);
    1925                 :            : 
    1926                 :          0 :       *symbol = get_symbol_for_decl (decl);
    1927                 :          0 :       *addrtype = hsa_get_segment_addr_type ((*symbol)->m_segment);
    1928                 :            :     }
    1929                 :          0 :   else if (TREE_CODE (base) == INTEGER_CST)
    1930                 :          0 :     *offset += wi::to_offset (base);
    1931                 :            :   else
    1932                 :          0 :     gcc_unreachable ();
    1933                 :            : }
    1934                 :            : 
    1935                 :            : /* Forward declaration of a function.  */
    1936                 :            : 
    1937                 :            : static void
    1938                 :            : gen_hsa_addr_insns (tree val, hsa_op_reg *dest, hsa_bb *hbb);
    1939                 :            : 
    1940                 :            : /* Generate HSA address operand for a given tree memory reference REF.  If
    1941                 :            :    instructions need to be created to calculate the address, they will be added
    1942                 :            :    to the end of HBB.  If a caller provider OUTPUT_BITSIZE and OUTPUT_BITPOS,
    1943                 :            :    the function assumes that the caller will handle possible
    1944                 :            :    bit-field references.  Otherwise if we reference a bit-field, sorry message
    1945                 :            :    is displayed.  */
    1946                 :            : 
    1947                 :            : static hsa_op_address *
    1948                 :          0 : gen_hsa_addr (tree ref, hsa_bb *hbb, HOST_WIDE_INT *output_bitsize = NULL,
    1949                 :            :               HOST_WIDE_INT *output_bitpos = NULL)
    1950                 :            : {
    1951                 :          0 :   hsa_symbol *symbol = NULL;
    1952                 :          0 :   hsa_op_reg *reg = NULL;
    1953                 :          0 :   offset_int offset = 0;
    1954                 :          0 :   tree origref = ref;
    1955                 :          0 :   tree varoffset = NULL_TREE;
    1956                 :          0 :   BrigType16_t addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
    1957                 :          0 :   HOST_WIDE_INT bitsize = 0, bitpos = 0;
    1958                 :          0 :   BrigType16_t flat_addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
    1959                 :            : 
    1960                 :          0 :   if (TREE_CODE (ref) == STRING_CST)
    1961                 :            :     {
    1962                 :          0 :       symbol = hsa_get_string_cst_symbol (ref);
    1963                 :          0 :       goto out;
    1964                 :            :     }
    1965                 :          0 :   else if (TREE_CODE (ref) == BIT_FIELD_REF
    1966                 :          0 :            && (!multiple_p (bit_field_size (ref), BITS_PER_UNIT)
    1967                 :          0 :                || !multiple_p (bit_field_offset (ref), BITS_PER_UNIT)))
    1968                 :            :     {
    1969                 :          0 :       HSA_SORRY_ATV (EXPR_LOCATION (origref),
    1970                 :            :                      "support for HSA does not implement "
    1971                 :            :                      "bit field references such as %E", ref);
    1972                 :          0 :       goto out;
    1973                 :            :     }
    1974                 :            : 
    1975                 :          0 :   if (handled_component_p (ref))
    1976                 :            :     {
    1977                 :          0 :       machine_mode mode;
    1978                 :          0 :       int unsignedp, volatilep, preversep;
    1979                 :          0 :       poly_int64 pbitsize, pbitpos;
    1980                 :          0 :       tree new_ref;
    1981                 :            : 
    1982                 :          0 :       new_ref = get_inner_reference (ref, &pbitsize, &pbitpos, &varoffset,
    1983                 :            :                                      &mode, &unsignedp, &preversep,
    1984                 :            :                                      &volatilep);
    1985                 :            :       /* When this isn't true, the switch below will report an
    1986                 :            :          appropriate error.  */
    1987                 :          0 :       if (pbitsize.is_constant () && pbitpos.is_constant ())
    1988                 :            :         {
    1989                 :          0 :           bitsize = pbitsize.to_constant ();
    1990                 :          0 :           bitpos = pbitpos.to_constant ();
    1991                 :          0 :           ref = new_ref;
    1992                 :          0 :           offset = bitpos;
    1993                 :          0 :           offset = wi::rshift (offset, LOG2_BITS_PER_UNIT, SIGNED);
    1994                 :            :         }
    1995                 :            :     }
    1996                 :            : 
    1997                 :          0 :   switch (TREE_CODE (ref))
    1998                 :            :     {
    1999                 :          0 :     case ADDR_EXPR:
    2000                 :          0 :       {
    2001                 :          0 :         addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_PRIVATE);
    2002                 :          0 :         symbol = hsa_cfun->create_hsa_temporary (flat_addrtype);
    2003                 :          0 :         hsa_op_reg *r = new hsa_op_reg (flat_addrtype);
    2004                 :          0 :         gen_hsa_addr_insns (ref, r, hbb);
    2005                 :          0 :         hbb->append_insn (new hsa_insn_mem (BRIG_OPCODE_ST, r->m_type,
    2006                 :          0 :                                             r, new hsa_op_address (symbol)));
    2007                 :            : 
    2008                 :          0 :         break;
    2009                 :            :       }
    2010                 :          0 :     case SSA_NAME:
    2011                 :          0 :       {
    2012                 :          0 :         addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_PRIVATE);
    2013                 :          0 :         hsa_op_with_type *r = hsa_cfun->reg_for_gimple_ssa (ref);
    2014                 :          0 :         if (r->m_type == BRIG_TYPE_B1)
    2015                 :          0 :           r = r->get_in_type (BRIG_TYPE_U32, hbb);
    2016                 :          0 :         symbol = hsa_cfun->create_hsa_temporary (r->m_type);
    2017                 :            : 
    2018                 :          0 :         hbb->append_insn (new hsa_insn_mem (BRIG_OPCODE_ST, r->m_type,
    2019                 :          0 :                                             r, new hsa_op_address (symbol)));
    2020                 :            : 
    2021                 :          0 :         break;
    2022                 :            :       }
    2023                 :          0 :     case PARM_DECL:
    2024                 :          0 :     case VAR_DECL:
    2025                 :          0 :     case RESULT_DECL:
    2026                 :          0 :     case CONST_DECL:
    2027                 :          0 :       gcc_assert (!symbol);
    2028                 :          0 :       symbol = get_symbol_for_decl (ref);
    2029                 :          0 :       addrtype = hsa_get_segment_addr_type (symbol->m_segment);
    2030                 :          0 :       break;
    2031                 :            : 
    2032                 :          0 :     case MEM_REF:
    2033                 :          0 :       process_mem_base (TREE_OPERAND (ref, 0), &symbol, &addrtype, &reg,
    2034                 :            :                         &offset, hbb);
    2035                 :            : 
    2036                 :          0 :       if (!integer_zerop (TREE_OPERAND (ref, 1)))
    2037                 :          0 :         offset += wi::to_offset (TREE_OPERAND (ref, 1));
    2038                 :            :       break;
    2039                 :            : 
    2040                 :          0 :     case TARGET_MEM_REF:
    2041                 :          0 :       process_mem_base (TMR_BASE (ref), &symbol, &addrtype, &reg, &offset, hbb);
    2042                 :          0 :       if (TMR_INDEX (ref))
    2043                 :            :         {
    2044                 :          0 :           hsa_op_reg *disp1;
    2045                 :          0 :           hsa_op_base *idx = hsa_cfun->reg_for_gimple_ssa
    2046                 :          0 :             (TMR_INDEX (ref))->get_in_type (addrtype, hbb);
    2047                 :          0 :           if (TMR_STEP (ref) && !integer_onep (TMR_STEP (ref)))
    2048                 :            :             {
    2049                 :          0 :               disp1 = new hsa_op_reg (addrtype);
    2050                 :          0 :               hsa_insn_basic *insn = new hsa_insn_basic (3, BRIG_OPCODE_MUL,
    2051                 :          0 :                                                          addrtype);
    2052                 :            : 
    2053                 :            :               /* As step must respect addrtype, we overwrite the type
    2054                 :            :                  of an immediate value.  */
    2055                 :          0 :               hsa_op_immed *step = new hsa_op_immed (TMR_STEP (ref));
    2056                 :          0 :               step->m_type = addrtype;
    2057                 :            : 
    2058                 :          0 :               insn->set_op (0, disp1);
    2059                 :          0 :               insn->set_op (1, idx);
    2060                 :          0 :               insn->set_op (2, step);
    2061                 :          0 :               hbb->append_insn (insn);
    2062                 :            :             }
    2063                 :            :           else
    2064                 :          0 :             disp1 = as_a <hsa_op_reg *> (idx);
    2065                 :          0 :           reg = add_addr_regs_if_needed (reg, disp1, hbb);
    2066                 :            :         }
    2067                 :          0 :       if (TMR_INDEX2 (ref))
    2068                 :            :         {
    2069                 :          0 :           if (TREE_CODE (TMR_INDEX2 (ref)) == SSA_NAME)
    2070                 :            :             {
    2071                 :          0 :               hsa_op_base *disp2 = hsa_cfun->reg_for_gimple_ssa
    2072                 :          0 :                 (TMR_INDEX2 (ref))->get_in_type (addrtype, hbb);
    2073                 :          0 :               reg = add_addr_regs_if_needed (reg, as_a <hsa_op_reg *> (disp2),
    2074                 :            :                                              hbb);
    2075                 :            :             }
    2076                 :          0 :           else if (TREE_CODE (TMR_INDEX2 (ref)) == INTEGER_CST)
    2077                 :          0 :             offset += wi::to_offset (TMR_INDEX2 (ref));
    2078                 :            :           else
    2079                 :          0 :             gcc_unreachable ();
    2080                 :            :         }
    2081                 :          0 :       offset += wi::to_offset (TMR_OFFSET (ref));
    2082                 :          0 :       break;
    2083                 :          0 :     case FUNCTION_DECL:
    2084                 :          0 :       HSA_SORRY_AT (EXPR_LOCATION (origref),
    2085                 :            :                     "support for HSA does not implement function pointers");
    2086                 :          0 :       goto out;
    2087                 :          0 :     default:
    2088                 :          0 :       HSA_SORRY_ATV (EXPR_LOCATION (origref), "support for HSA does "
    2089                 :            :                      "not implement memory access to %E", origref);
    2090                 :          0 :       goto out;
    2091                 :            :     }
    2092                 :            : 
    2093                 :          0 :   if (varoffset)
    2094                 :            :     {
    2095                 :          0 :       if (TREE_CODE (varoffset) == INTEGER_CST)
    2096                 :          0 :         offset += wi::to_offset (varoffset);
    2097                 :            :       else
    2098                 :            :         {
    2099                 :          0 :           hsa_op_base *off_op = gen_address_calculation (varoffset, hbb,
    2100                 :            :                                                          addrtype);
    2101                 :          0 :           reg = add_addr_regs_if_needed (reg, as_a <hsa_op_reg *> (off_op),
    2102                 :            :                                          hbb);
    2103                 :            :         }
    2104                 :            :     }
    2105                 :            : 
    2106                 :          0 :   gcc_checking_assert ((symbol
    2107                 :            :                         && addrtype
    2108                 :            :                         == hsa_get_segment_addr_type (symbol->m_segment))
    2109                 :            :                        || (!symbol
    2110                 :            :                            && addrtype
    2111                 :            :                            == hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT)));
    2112                 :          0 : out:
    2113                 :          0 :   HOST_WIDE_INT hwi_offset = offset.to_shwi ();
    2114                 :            : 
    2115                 :            :   /* Calculate remaining bitsize offset (if presented).  */
    2116                 :          0 :   bitpos %= BITS_PER_UNIT;
    2117                 :            :   /* If bitsize is a power of two that is greater or equal to BITS_PER_UNIT, it
    2118                 :            :      is not a reason to think this is a bit-field access.  */
    2119                 :          0 :   if (bitpos == 0
    2120                 :          0 :       && (bitsize >= BITS_PER_UNIT)
    2121                 :          0 :       && !(bitsize & (bitsize - 1)))
    2122                 :          0 :     bitsize = 0;
    2123                 :            : 
    2124                 :          0 :   if ((bitpos || bitsize) && (output_bitpos == NULL || output_bitsize == NULL))
    2125                 :          0 :     HSA_SORRY_ATV (EXPR_LOCATION (origref), "support for HSA does not "
    2126                 :            :                    "implement unhandled bit field reference such as %E", ref);
    2127                 :            : 
    2128                 :          0 :   if (output_bitsize != NULL && output_bitpos != NULL)
    2129                 :            :     {
    2130                 :          0 :       *output_bitsize = bitsize;
    2131                 :          0 :       *output_bitpos = bitpos;
    2132                 :            :     }
    2133                 :            : 
    2134                 :          0 :   return new hsa_op_address (symbol, reg, hwi_offset);
    2135                 :            : }
    2136                 :            : 
    2137                 :            : /* Generate HSA address operand for a given tree memory reference REF.  If
    2138                 :            :    instructions need to be created to calculate the address, they will be added
    2139                 :            :    to the end of HBB.  OUTPUT_ALIGN is alignment of the created address.  */
    2140                 :            : 
    2141                 :            : static hsa_op_address *
    2142                 :          0 : gen_hsa_addr_with_align (tree ref, hsa_bb *hbb, BrigAlignment8_t *output_align)
    2143                 :            : {
    2144                 :          0 :   hsa_op_address *addr = gen_hsa_addr (ref, hbb);
    2145                 :          0 :   if (addr->m_reg || !addr->m_symbol)
    2146                 :          0 :     *output_align = hsa_object_alignment (ref);
    2147                 :            :   else
    2148                 :            :     {
    2149                 :            :       /* If the address consists only of a symbol and an offset, we
    2150                 :            :          compute the alignment ourselves to take into account any alignment
    2151                 :            :          promotions we might have done for the HSA symbol representation.  */
    2152                 :          0 :       unsigned align = hsa_byte_alignment (addr->m_symbol->m_align);
    2153                 :          0 :       unsigned misalign = addr->m_imm_offset & (align - 1);
    2154                 :          0 :       if (misalign)
    2155                 :          0 :         align = least_bit_hwi (misalign);
    2156                 :          0 :       *output_align = hsa_alignment_encoding (BITS_PER_UNIT * align);
    2157                 :            :     }
    2158                 :          0 :   return addr;
    2159                 :            : }
    2160                 :            : 
    2161                 :            : /* Generate HSA address for a function call argument of given TYPE.
    2162                 :            :    INDEX is used to generate corresponding name of the arguments.
    2163                 :            :    Special value -1 represents fact that result value is created.  */
    2164                 :            : 
    2165                 :            : static hsa_op_address *
    2166                 :          0 : gen_hsa_addr_for_arg (tree tree_type, int index)
    2167                 :            : {
    2168                 :          0 :   hsa_symbol *sym = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_ARG,
    2169                 :          0 :                                     BRIG_LINKAGE_ARG);
    2170                 :          0 :   sym->m_type = hsa_type_for_tree_type (tree_type, &sym->m_dim);
    2171                 :            : 
    2172                 :          0 :   if (index == -1) /* Function result.  */
    2173                 :          0 :     sym->m_name = "res";
    2174                 :            :   else /* Function call arguments.  */
    2175                 :            :     {
    2176                 :          0 :       sym->m_name = NULL;
    2177                 :          0 :       sym->m_name_number = index;
    2178                 :            :     }
    2179                 :            : 
    2180                 :          0 :   return new hsa_op_address (sym);
    2181                 :            : }
    2182                 :            : 
    2183                 :            : /* Generate HSA instructions that process all necessary conversions
    2184                 :            :    of an ADDR to flat addressing and place the result into DEST.
    2185                 :            :    Instructions are appended to HBB.  */
    2186                 :            : 
    2187                 :            : static void
    2188                 :          0 : convert_addr_to_flat_segment (hsa_op_address *addr, hsa_op_reg *dest,
    2189                 :            :                               hsa_bb *hbb)
    2190                 :            : {
    2191                 :          0 :   hsa_insn_basic *insn = new hsa_insn_basic (2, BRIG_OPCODE_LDA);
    2192                 :          0 :   insn->set_op (1, addr);
    2193                 :          0 :   if (addr->m_symbol && addr->m_symbol->m_segment != BRIG_SEGMENT_GLOBAL)
    2194                 :            :     {
    2195                 :            :       /* LDA produces segment-relative address, we need to convert
    2196                 :            :          it to the flat one.  */
    2197                 :          0 :       hsa_op_reg *tmp;
    2198                 :          0 :       tmp = new hsa_op_reg (hsa_get_segment_addr_type
    2199                 :          0 :                             (addr->m_symbol->m_segment));
    2200                 :          0 :       hsa_insn_seg *seg;
    2201                 :          0 :       seg = new hsa_insn_seg (BRIG_OPCODE_STOF,
    2202                 :          0 :                               hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT),
    2203                 :          0 :                               tmp->m_type, addr->m_symbol->m_segment, dest,
    2204                 :          0 :                               tmp);
    2205                 :            : 
    2206                 :          0 :       insn->set_op (0, tmp);
    2207                 :          0 :       insn->m_type = tmp->m_type;
    2208                 :          0 :       hbb->append_insn (insn);
    2209                 :          0 :       hbb->append_insn (seg);
    2210                 :            :     }
    2211                 :            :   else
    2212                 :            :     {
    2213                 :          0 :       insn->set_op (0, dest);
    2214                 :          0 :       insn->m_type = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
    2215                 :          0 :       hbb->append_insn (insn);
    2216                 :            :     }
    2217                 :          0 : }
    2218                 :            : 
    2219                 :            : /* Generate HSA instructions that calculate address of VAL including all
    2220                 :            :    necessary conversions to flat addressing and place the result into DEST.
    2221                 :            :    Instructions are appended to HBB.  */
    2222                 :            : 
    2223                 :            : static void
    2224                 :          0 : gen_hsa_addr_insns (tree val, hsa_op_reg *dest, hsa_bb *hbb)
    2225                 :            : {
    2226                 :            :   /* Handle cases like tmp = NULL, where we just emit a move instruction
    2227                 :            :      to a register.  */
    2228                 :          0 :   if (TREE_CODE (val) == INTEGER_CST)
    2229                 :            :     {
    2230                 :          0 :       hsa_op_immed *c = new hsa_op_immed (val);
    2231                 :          0 :       hsa_insn_basic *insn = new hsa_insn_basic (2, BRIG_OPCODE_MOV,
    2232                 :          0 :                                                  dest->m_type, dest, c);
    2233                 :          0 :       hbb->append_insn (insn);
    2234                 :          0 :       return;
    2235                 :            :     }
    2236                 :            : 
    2237                 :          0 :   hsa_op_address *addr;
    2238                 :            : 
    2239                 :          0 :   gcc_assert (dest->m_type == hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT));
    2240                 :          0 :   if (TREE_CODE (val) == ADDR_EXPR)
    2241                 :          0 :     val = TREE_OPERAND (val, 0);
    2242                 :          0 :   addr = gen_hsa_addr (val, hbb);
    2243                 :            : 
    2244                 :          0 :   if (TREE_CODE (val) == CONST_DECL
    2245                 :          0 :       && is_gimple_reg_type (TREE_TYPE (val)))
    2246                 :            :     {
    2247                 :          0 :       gcc_assert (addr->m_symbol
    2248                 :            :                   && addr->m_symbol->m_segment == BRIG_SEGMENT_READONLY);
    2249                 :            :       /* CONST_DECLs are in readonly segment which however does not have
    2250                 :            :          addresses convertible to flat segments.  So copy it to a private one
    2251                 :            :          and take address of that.  */
    2252                 :          0 :       BrigType16_t csttype
    2253                 :          0 :         = mem_type_for_type (hsa_type_for_scalar_tree_type (TREE_TYPE (val),
    2254                 :            :                                                             false));
    2255                 :          0 :       hsa_op_reg *r = new hsa_op_reg (csttype);
    2256                 :          0 :       hbb->append_insn (new hsa_insn_mem (BRIG_OPCODE_LD, csttype, r,
    2257                 :          0 :                                           new hsa_op_address (addr->m_symbol)));
    2258                 :          0 :       hsa_symbol *copysym = hsa_cfun->create_hsa_temporary (csttype);
    2259                 :          0 :       hbb->append_insn (new hsa_insn_mem (BRIG_OPCODE_ST, csttype, r,
    2260                 :          0 :                                           new hsa_op_address (copysym)));
    2261                 :          0 :       addr->m_symbol = copysym;
    2262                 :            :     }
    2263                 :          0 :   else if (addr->m_symbol && addr->m_symbol->m_segment == BRIG_SEGMENT_READONLY)
    2264                 :            :     {
    2265                 :          0 :       HSA_SORRY_ATV (EXPR_LOCATION (val), "support for HSA does "
    2266                 :            :                      "not implement taking addresses of complex "
    2267                 :            :                      "%<CONST_DECL%> such as %E", val);
    2268                 :          0 :       return;
    2269                 :            :     }
    2270                 :            : 
    2271                 :            : 
    2272                 :          0 :   convert_addr_to_flat_segment (addr, dest, hbb);
    2273                 :            : }
    2274                 :            : 
    2275                 :            : /* Return an HSA register or HSA immediate value operand corresponding to
    2276                 :            :    gimple operand OP.  */
    2277                 :            : 
    2278                 :            : static hsa_op_with_type *
    2279                 :          0 : hsa_reg_or_immed_for_gimple_op (tree op, hsa_bb *hbb)
    2280                 :            : {
    2281                 :          0 :   hsa_op_reg *tmp;
    2282                 :            : 
    2283                 :          0 :   if (TREE_CODE (op) == SSA_NAME)
    2284                 :          0 :     tmp = hsa_cfun->reg_for_gimple_ssa (op);
    2285                 :          0 :   else if (!POINTER_TYPE_P (TREE_TYPE (op)))
    2286                 :          0 :     return new hsa_op_immed (op);
    2287                 :            :   else
    2288                 :            :     {
    2289                 :          0 :       tmp = new hsa_op_reg (hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT));
    2290                 :          0 :       gen_hsa_addr_insns (op, tmp, hbb);
    2291                 :            :     }
    2292                 :            :   return tmp;
    2293                 :            : }
    2294                 :            : 
    2295                 :            : /* Create a simple movement instruction with register destination DEST and
    2296                 :            :    register or immediate source SRC and append it to the end of HBB.  */
    2297                 :            : 
    2298                 :            : void
    2299                 :          0 : hsa_build_append_simple_mov (hsa_op_reg *dest, hsa_op_base *src, hsa_bb *hbb)
    2300                 :            : {
    2301                 :            :   /* Moves of packed data between registers need to adhere to the same type
    2302                 :            :      rules like when dealing with memory.  */
    2303                 :          0 :   BrigType16_t tp = mem_type_for_type (dest->m_type);
    2304                 :          0 :   hsa_insn_basic *insn = new hsa_insn_basic (2, BRIG_OPCODE_MOV, tp, dest, src);
    2305                 :          0 :   hsa_fixup_mov_insn_type (insn);
    2306                 :          0 :   unsigned dest_size = hsa_type_bit_size (dest->m_type);
    2307                 :          0 :   if (hsa_op_reg *sreg = dyn_cast <hsa_op_reg *> (src))
    2308                 :          0 :     gcc_assert (dest_size == hsa_type_bit_size (sreg->m_type));
    2309                 :            :   else
    2310                 :            :     {
    2311                 :          0 :       unsigned imm_size
    2312                 :          0 :         =  hsa_type_bit_size (as_a <hsa_op_immed *> (src)->m_type);
    2313                 :          0 :       gcc_assert ((dest_size == imm_size)
    2314                 :            :                   /* Eventually < 32bit registers will be promoted to 32bit. */
    2315                 :            :                   || (dest_size < 32 && imm_size == 32));
    2316                 :            :     }
    2317                 :          0 :   hbb->append_insn (insn);
    2318                 :          0 : }
    2319                 :            : 
    2320                 :            : /* Generate HSAIL instructions loading a bit field into register DEST.
    2321                 :            :    VALUE_REG is a register of a SSA name that is used in the bit field
    2322                 :            :    reference.  To identify a bit field BITPOS is offset to the loaded memory
    2323                 :            :    and BITSIZE is number of bits of the bit field.
    2324                 :            :    Add instructions to HBB.  */
    2325                 :            : 
    2326                 :            : static void
    2327                 :          0 : gen_hsa_insns_for_bitfield (hsa_op_reg *dest, hsa_op_reg *value_reg,
    2328                 :            :                             HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
    2329                 :            :                             hsa_bb *hbb)
    2330                 :            : {
    2331                 :          0 :   unsigned type_bitsize
    2332                 :          0 :     = hsa_type_bit_size (hsa_extend_inttype_to_32bit (dest->m_type));
    2333                 :          0 :   unsigned left_shift = type_bitsize - (bitsize + bitpos);
    2334                 :          0 :   unsigned right_shift = left_shift + bitpos;
    2335                 :            : 
    2336                 :          0 :   if (left_shift)
    2337                 :            :     {
    2338                 :          0 :       hsa_op_reg *value_reg_2
    2339                 :          0 :         = new hsa_op_reg (hsa_extend_inttype_to_32bit (dest->m_type));
    2340                 :          0 :       hsa_op_immed *c = new hsa_op_immed (left_shift, BRIG_TYPE_U32);
    2341                 :            : 
    2342                 :          0 :       hsa_insn_basic *lshift
    2343                 :          0 :         = new hsa_insn_basic (3, BRIG_OPCODE_SHL, value_reg_2->m_type,
    2344                 :          0 :                               value_reg_2, value_reg, c);
    2345                 :            : 
    2346                 :          0 :       hbb->append_insn (lshift);
    2347                 :            : 
    2348                 :          0 :       value_reg = value_reg_2;
    2349                 :            :     }
    2350                 :            : 
    2351                 :          0 :   if (right_shift)
    2352                 :            :     {
    2353                 :          0 :       hsa_op_reg *value_reg_2
    2354                 :          0 :         = new hsa_op_reg (hsa_extend_inttype_to_32bit (dest->m_type));
    2355                 :          0 :       hsa_op_immed *c = new hsa_op_immed (right_shift, BRIG_TYPE_U32);
    2356                 :            : 
    2357                 :          0 :       hsa_insn_basic *rshift
    2358                 :          0 :         = new hsa_insn_basic (3, BRIG_OPCODE_SHR, value_reg_2->m_type,
    2359                 :          0 :                               value_reg_2, value_reg, c);
    2360                 :            : 
    2361                 :          0 :       hbb->append_insn (rshift);
    2362                 :            : 
    2363                 :          0 :       value_reg = value_reg_2;
    2364                 :            :     }
    2365                 :            : 
    2366                 :          0 :     hsa_insn_basic *assignment
    2367                 :          0 :       = new hsa_insn_basic (2, BRIG_OPCODE_MOV, dest->m_type, NULL, value_reg);
    2368                 :          0 :     hsa_fixup_mov_insn_type (assignment);
    2369                 :          0 :     hbb->append_insn (assignment);
    2370                 :          0 :     assignment->set_output_in_type (dest, 0, hbb);
    2371                 :          0 : }
    2372                 :            : 
    2373                 :            : 
    2374                 :            : /* Generate HSAIL instructions loading a bit field into register DEST.  ADDR is
    2375                 :            :    prepared memory address which is used to load the bit field.  To identify a
    2376                 :            :    bit field BITPOS is offset to the loaded memory and BITSIZE is number of
    2377                 :            :    bits of the bit field.  Add instructions to HBB.  Load must be performed in
    2378                 :            :    alignment ALIGN.  */
    2379                 :            : 
    2380                 :            : static void
    2381                 :          0 : gen_hsa_insns_for_bitfield_load (hsa_op_reg *dest, hsa_op_address *addr,
    2382                 :            :                                  HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
    2383                 :            :                                  hsa_bb *hbb, BrigAlignment8_t align)
    2384                 :            : {
    2385                 :          0 :   hsa_op_reg *value_reg = new hsa_op_reg (dest->m_type);
    2386                 :          0 :   hsa_insn_mem *mem
    2387                 :            :   = new hsa_insn_mem (BRIG_OPCODE_LD,
    2388                 :          0 :                       hsa_extend_inttype_to_32bit (dest->m_type),
    2389                 :          0 :                       value_reg, addr);
    2390                 :          0 :   mem->set_align (align);
    2391                 :          0 :   hbb->append_insn (mem);
    2392                 :          0 :   gen_hsa_insns_for_bitfield (dest, value_reg, bitsize, bitpos, hbb);
    2393                 :          0 : }
    2394                 :            : 
    2395                 :            : /* Return the alignment of base memory accesses we issue to perform bit-field
    2396                 :            :    memory access REF.  */
    2397                 :            : 
    2398                 :            : static BrigAlignment8_t
    2399                 :          0 : hsa_bitmemref_alignment (tree ref)
    2400                 :            : {
    2401                 :          0 :   unsigned HOST_WIDE_INT bit_offset = 0;
    2402                 :            : 
    2403                 :          0 :   while (true)
    2404                 :            :     {
    2405                 :          0 :       if (TREE_CODE (ref) == BIT_FIELD_REF)
    2406                 :            :         {
    2407                 :          0 :           if (!tree_fits_uhwi_p (TREE_OPERAND (ref, 2)))
    2408                 :            :             return BRIG_ALIGNMENT_1;
    2409                 :          0 :           bit_offset += tree_to_uhwi (TREE_OPERAND (ref, 2));
    2410                 :            :         }
    2411                 :          0 :       else if (TREE_CODE (ref) == COMPONENT_REF
    2412                 :          0 :                && DECL_BIT_FIELD (TREE_OPERAND (ref, 1)))
    2413                 :          0 :         bit_offset += int_bit_position (TREE_OPERAND (ref, 1));
    2414                 :            :       else
    2415                 :            :         break;
    2416                 :          0 :       ref = TREE_OPERAND (ref, 0);
    2417                 :            :     }
    2418                 :            : 
    2419                 :          0 :   unsigned HOST_WIDE_INT bits = bit_offset % BITS_PER_UNIT;
    2420                 :          0 :   unsigned HOST_WIDE_INT byte_bits = bit_offset - bits;
    2421                 :          0 :   BrigAlignment8_t base = hsa_object_alignment (ref);
    2422                 :          0 :   if (byte_bits == 0)
    2423                 :            :     return base;
    2424                 :          0 :   return MIN (base, hsa_alignment_encoding (least_bit_hwi (byte_bits)));
    2425                 :            : }
    2426                 :            : 
    2427                 :            : /* Generate HSAIL instructions loading something into register DEST.  RHS is
    2428                 :            :    tree representation of the loaded data, which are loaded as type TYPE.  Add
    2429                 :            :    instructions to HBB.  */
    2430                 :            : 
    2431                 :            : static void
    2432                 :          0 : gen_hsa_insns_for_load (hsa_op_reg *dest, tree rhs, tree type, hsa_bb *hbb)
    2433                 :            : {
    2434                 :            :   /* The destination SSA name will give us the type.  */
    2435                 :          0 :   if (TREE_CODE (rhs) == VIEW_CONVERT_EXPR)
    2436                 :          0 :     rhs = TREE_OPERAND (rhs, 0);
    2437                 :            : 
    2438                 :          0 :   if (TREE_CODE (rhs) == SSA_NAME)
    2439                 :            :     {
    2440                 :          0 :       hsa_op_reg *src = hsa_cfun->reg_for_gimple_ssa (rhs);
    2441                 :          0 :       hsa_build_append_simple_mov (dest, src, hbb);
    2442                 :            :     }
    2443                 :          0 :   else if (is_gimple_min_invariant (rhs)
    2444                 :          0 :            || TREE_CODE (rhs) == ADDR_EXPR)
    2445                 :            :     {
    2446                 :          0 :       if (POINTER_TYPE_P (TREE_TYPE (rhs)))
    2447                 :            :         {
    2448                 :          0 :           if (dest->m_type != hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT))
    2449                 :            :             {
    2450                 :          0 :               HSA_SORRY_ATV (EXPR_LOCATION (rhs),
    2451                 :            :                              "support for HSA does not implement conversion "
    2452                 :            :                              "of %E to the requested non-pointer type", rhs);
    2453                 :          0 :               return;
    2454                 :            :             }
    2455                 :            : 
    2456                 :          0 :           gen_hsa_addr_insns (rhs, dest, hbb);
    2457                 :            :         }
    2458                 :          0 :       else if (TREE_CODE (rhs) == COMPLEX_CST)
    2459                 :            :         {
    2460                 :          0 :           hsa_op_immed *real_part = new hsa_op_immed (TREE_REALPART (rhs));
    2461                 :          0 :           hsa_op_immed *imag_part = new hsa_op_immed (TREE_IMAGPART (rhs));
    2462                 :            : 
    2463                 :          0 :           hsa_op_reg *real_part_reg
    2464                 :          0 :             = new hsa_op_reg (hsa_type_for_scalar_tree_type (TREE_TYPE (type),
    2465                 :          0 :                                                              true));
    2466                 :          0 :           hsa_op_reg *imag_part_reg
    2467                 :          0 :             = new hsa_op_reg (hsa_type_for_scalar_tree_type (TREE_TYPE (type),
    2468                 :          0 :                                                              true));
    2469                 :            : 
    2470                 :          0 :           hsa_build_append_simple_mov (real_part_reg, real_part, hbb);
    2471                 :          0 :           hsa_build_append_simple_mov (imag_part_reg, imag_part, hbb);
    2472                 :            : 
    2473                 :          0 :           BrigType16_t src_type = hsa_bittype_for_type (real_part_reg->m_type);
    2474                 :            : 
    2475                 :          0 :           hsa_insn_packed *insn
    2476                 :          0 :             = new hsa_insn_packed (3, BRIG_OPCODE_COMBINE, dest->m_type,
    2477                 :            :                                    src_type, dest, real_part_reg,
    2478                 :          0 :                                    imag_part_reg);
    2479                 :          0 :           hbb->append_insn (insn);
    2480                 :            :         }
    2481                 :            :       else
    2482                 :            :         {
    2483                 :          0 :           hsa_op_immed *imm = new hsa_op_immed (rhs);
    2484                 :          0 :           hsa_build_append_simple_mov (dest, imm, hbb);
    2485                 :            :         }
    2486                 :            :     }
    2487                 :          0 :   else if (TREE_CODE (rhs) == REALPART_EXPR || TREE_CODE (rhs) == IMAGPART_EXPR)
    2488                 :            :     {
    2489                 :          0 :       tree pack_type = TREE_TYPE (TREE_OPERAND (rhs, 0));
    2490                 :            : 
    2491                 :          0 :       hsa_op_reg *packed_reg
    2492                 :          0 :         = new hsa_op_reg (hsa_type_for_scalar_tree_type (pack_type, true));
    2493                 :            : 
    2494                 :          0 :       tree complex_rhs = TREE_OPERAND (rhs, 0);
    2495                 :          0 :       gen_hsa_insns_for_load (packed_reg, complex_rhs, TREE_TYPE (complex_rhs),
    2496                 :            :                               hbb);
    2497                 :            : 
    2498                 :          0 :       hsa_op_reg *real_reg
    2499                 :          0 :         = new hsa_op_reg (hsa_type_for_scalar_tree_type (type, true));
    2500                 :            : 
    2501                 :          0 :       hsa_op_reg *imag_reg
    2502                 :          0 :         = new hsa_op_reg (hsa_type_for_scalar_tree_type (type, true));
    2503                 :            : 
    2504                 :          0 :       BrigKind16_t brig_type = packed_reg->m_type;
    2505                 :          0 :       hsa_insn_packed *packed
    2506                 :            :         = new hsa_insn_packed (3, BRIG_OPCODE_EXPAND,
    2507                 :          0 :                                hsa_bittype_for_type (real_reg->m_type),
    2508                 :          0 :          brig_type, real_reg, imag_reg, packed_reg);
    2509                 :            : 
    2510                 :          0 :       hbb->append_insn (packed);
    2511                 :            : 
    2512                 :          0 :       hsa_op_reg *source = TREE_CODE (rhs) == REALPART_EXPR ?
    2513                 :            :         real_reg : imag_reg;
    2514                 :            : 
    2515                 :          0 :       hsa_insn_basic *insn = new hsa_insn_basic (2, BRIG_OPCODE_MOV,
    2516                 :          0 :                                                  dest->m_type, NULL, source);
    2517                 :          0 :       hsa_fixup_mov_insn_type (insn);
    2518                 :          0 :       hbb->append_insn (insn);
    2519                 :          0 :       insn->set_output_in_type (dest, 0, hbb);
    2520                 :            :     }
    2521                 :          0 :   else if (TREE_CODE (rhs) == BIT_FIELD_REF
    2522                 :          0 :            && TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME)
    2523                 :            :     {
    2524                 :          0 :       tree ssa_name = TREE_OPERAND (rhs, 0);
    2525                 :          0 :       HOST_WIDE_INT bitsize = tree_to_uhwi (TREE_OPERAND (rhs, 1));
    2526                 :          0 :       HOST_WIDE_INT bitpos = tree_to_uhwi (TREE_OPERAND (rhs, 2));
    2527                 :            : 
    2528                 :          0 :       hsa_op_reg *imm_value = hsa_cfun->reg_for_gimple_ssa (ssa_name);
    2529                 :          0 :       gen_hsa_insns_for_bitfield (dest, imm_value, bitsize, bitpos, hbb);
    2530                 :            :     }
    2531                 :          0 :   else if (DECL_P (rhs) || TREE_CODE (rhs) == MEM_REF
    2532                 :          0 :            || TREE_CODE (rhs) == TARGET_MEM_REF
    2533                 :          0 :            || handled_component_p (rhs))
    2534                 :            :     {
    2535                 :          0 :       HOST_WIDE_INT bitsize, bitpos;
    2536                 :            : 
    2537                 :            :       /* Load from memory.  */
    2538                 :          0 :       hsa_op_address *addr;
    2539                 :          0 :       addr = gen_hsa_addr (rhs, hbb, &bitsize, &bitpos);
    2540                 :            : 
    2541                 :            :       /* Handle load of a bit field.  */
    2542                 :          0 :       if (bitsize > 64)
    2543                 :            :         {
    2544                 :          0 :           HSA_SORRY_AT (EXPR_LOCATION (rhs),
    2545                 :            :                         "support for HSA does not implement load from a bit "
    2546                 :            :                         "field bigger than 64 bits");
    2547                 :          0 :           return;
    2548                 :            :         }
    2549                 :            : 
    2550                 :          0 :       if (bitsize || bitpos)
    2551                 :          0 :         gen_hsa_insns_for_bitfield_load (dest, addr, bitsize, bitpos, hbb,
    2552                 :          0 :                                          hsa_bitmemref_alignment (rhs));
    2553                 :            :       else
    2554                 :            :         {
    2555                 :          0 :           BrigType16_t mtype;
    2556                 :            :           /* Not dest->m_type, that's possibly extended.  */
    2557                 :          0 :           mtype = mem_type_for_type (hsa_type_for_scalar_tree_type (type,
    2558                 :            :                                                                     false));
    2559                 :          0 :           hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, mtype, dest,
    2560                 :          0 :                                                 addr);
    2561                 :          0 :           mem->set_align (hsa_object_alignment (rhs));
    2562                 :          0 :           hbb->append_insn (mem);
    2563                 :            :         }
    2564                 :            :     }
    2565                 :            :   else
    2566                 :          0 :     HSA_SORRY_ATV (EXPR_LOCATION (rhs),
    2567                 :            :                    "support for HSA does not implement loading "
    2568                 :            :                    "of expression %E",
    2569                 :            :                    rhs);
    2570                 :            : }
    2571                 :            : 
    2572                 :            : /* Return number of bits necessary for representation of a bit field,
    2573                 :            :    starting at BITPOS with size of BITSIZE.  */
    2574                 :            : 
    2575                 :            : static unsigned
    2576                 :          0 : get_bitfield_size (unsigned bitpos, unsigned bitsize)
    2577                 :            : {
    2578                 :          0 :   unsigned s = bitpos + bitsize;
    2579                 :          0 :   unsigned sizes[] = {8, 16, 32, 64};
    2580                 :            : 
    2581                 :          0 :   for (unsigned i = 0; i < 4; i++)
    2582                 :          0 :     if (s <= sizes[i])
    2583                 :          0 :       return sizes[i];
    2584                 :            : 
    2585                 :          0 :   gcc_unreachable ();
    2586                 :            :   return 0;
    2587                 :            : }
    2588                 :            : 
    2589                 :            : /* Generate HSAIL instructions storing into memory.  LHS is the destination of
    2590                 :            :    the store, SRC is the source operand.  Add instructions to HBB.  */
    2591                 :            : 
    2592                 :            : static void
    2593                 :          0 : gen_hsa_insns_for_store (tree lhs, hsa_op_base *src, hsa_bb *hbb)
    2594                 :            : {
    2595                 :          0 :   HOST_WIDE_INT bitsize = 0, bitpos = 0;
    2596                 :          0 :   BrigAlignment8_t req_align;
    2597                 :          0 :   BrigType16_t mtype;
    2598                 :          0 :   mtype = mem_type_for_type (hsa_type_for_scalar_tree_type (TREE_TYPE (lhs),
    2599                 :            :                                                             false));
    2600                 :          0 :   hsa_op_address *addr;
    2601                 :          0 :   addr = gen_hsa_addr (lhs, hbb, &bitsize, &bitpos);
    2602                 :            : 
    2603                 :            :   /* Handle store to a bit field.  */
    2604                 :          0 :   if (bitsize > 64)
    2605                 :            :     {
    2606                 :          0 :       HSA_SORRY_AT (EXPR_LOCATION (lhs),
    2607                 :            :                     "support for HSA does not implement store to a bit field "
    2608                 :            :                     "bigger than 64 bits");
    2609                 :          0 :       return;
    2610                 :            :     }
    2611                 :            : 
    2612                 :          0 :   unsigned type_bitsize = get_bitfield_size (bitpos, bitsize);
    2613                 :            : 
    2614                 :            :   /* HSAIL does not support MOV insn with 16-bits integers.  */
    2615                 :          0 :   if (type_bitsize < 32)
    2616                 :            :     type_bitsize = 32;
    2617                 :            : 
    2618                 :          0 :   if (bitpos || (bitsize && type_bitsize != bitsize))
    2619                 :            :     {
    2620                 :          0 :       unsigned HOST_WIDE_INT mask = 0;
    2621                 :          0 :       BrigType16_t mem_type
    2622                 :          0 :         = get_integer_type_by_bytes (type_bitsize / BITS_PER_UNIT,
    2623                 :          0 :                                      !TYPE_UNSIGNED (TREE_TYPE (lhs)));
    2624                 :            : 
    2625                 :          0 :       for (unsigned i = 0; i < type_bitsize; i++)
    2626                 :          0 :         if (i < bitpos || i >= bitpos + bitsize)
    2627                 :          0 :           mask |= ((unsigned HOST_WIDE_INT)1 << i);
    2628                 :            : 
    2629                 :          0 :       hsa_op_reg *value_reg = new hsa_op_reg (mem_type);
    2630                 :            : 
    2631                 :          0 :       req_align = hsa_bitmemref_alignment (lhs);
    2632                 :            :       /* Load value from memory.  */
    2633                 :          0 :       hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, mem_type,
    2634                 :          0 :                                             value_reg, addr);
    2635                 :          0 :       mem->set_align (req_align);
    2636                 :          0 :       hbb->append_insn (mem);
    2637                 :            : 
    2638                 :            :       /* AND the loaded value with prepared mask.  */
    2639                 :          0 :       hsa_op_reg *cleared_reg = new hsa_op_reg (mem_type);
    2640                 :            : 
    2641                 :          0 :       BrigType16_t t
    2642                 :          0 :         = get_integer_type_by_bytes (type_bitsize / BITS_PER_UNIT, false);
    2643                 :          0 :       hsa_op_immed *c = new hsa_op_immed (mask, t);
    2644                 :            : 
    2645                 :          0 :       hsa_insn_basic *clearing
    2646                 :            :         = new hsa_insn_basic (3, BRIG_OPCODE_AND, mem_type, cleared_reg,
    2647                 :          0 :                               value_reg, c);
    2648                 :          0 :       hbb->append_insn (clearing);
    2649                 :            : 
    2650                 :            :       /* Shift to left a value that is going to be stored.  */
    2651                 :          0 :       hsa_op_reg *new_value_reg = new hsa_op_reg (mem_type);
    2652                 :            : 
    2653                 :          0 :       hsa_insn_basic *basic = new hsa_insn_basic (2, BRIG_OPCODE_MOV, mem_type,
    2654                 :          0 :                                                   new_value_reg, src);
    2655                 :          0 :       hsa_fixup_mov_insn_type (basic);
    2656                 :          0 :       hbb->append_insn (basic);
    2657                 :            : 
    2658                 :          0 :       if (bitpos)
    2659                 :            :         {
    2660                 :          0 :           hsa_op_reg *shifted_value_reg = new hsa_op_reg (mem_type);
    2661                 :          0 :           c = new hsa_op_immed (bitpos, BRIG_TYPE_U32);
    2662                 :            : 
    2663                 :          0 :           hsa_insn_basic *basic
    2664                 :            :             = new hsa_insn_basic (3, BRIG_OPCODE_SHL, mem_type,
    2665                 :          0 :                                   shifted_value_reg, new_value_reg, c);
    2666                 :          0 :           hbb->append_insn (basic);
    2667                 :            : 
    2668                 :          0 :           new_value_reg = shifted_value_reg;
    2669                 :            :         }
    2670                 :            : 
    2671                 :            :       /* OR the prepared value with prepared chunk loaded from memory.  */
    2672                 :          0 :       hsa_op_reg *prepared_reg= new hsa_op_reg (mem_type);
    2673                 :          0 :       basic = new hsa_insn_basic (3, BRIG_OPCODE_OR, mem_type, prepared_reg,
    2674                 :          0 :                                   new_value_reg, cleared_reg);
    2675                 :          0 :       hbb->append_insn (basic);
    2676                 :            : 
    2677                 :          0 :       src = prepared_reg;
    2678                 :          0 :       mtype = mem_type;
    2679                 :            :     }
    2680                 :            :   else
    2681                 :          0 :     req_align = hsa_object_alignment (lhs);
    2682                 :            : 
    2683                 :          0 :   hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, mtype, src, addr);
    2684                 :          0 :   mem->set_align (req_align);
    2685                 :            : 
    2686                 :            :   /* The HSAIL verifier has another constraint: if the source is an immediate
    2687                 :            :      then it must match the destination type.  If it's a register the low bits
    2688                 :            :      will be used for sub-word stores.  We're always allocating new operands so
    2689                 :            :      we can modify the above in place.  */
    2690                 :          0 :   if (hsa_op_immed *imm = dyn_cast <hsa_op_immed *> (src))
    2691                 :            :     {
    2692                 :          0 :       if (!hsa_type_packed_p (imm->m_type))
    2693                 :          0 :         imm->m_type = mem->m_type;
    2694                 :            :       else
    2695                 :            :         {
    2696                 :            :           /* ...and all vector immediates apparently need to be vectors of
    2697                 :            :              unsigned bytes.  */
    2698                 :          0 :           unsigned bs = hsa_type_bit_size (imm->m_type);
    2699                 :          0 :           gcc_assert (bs == hsa_type_bit_size (mem->m_type));
    2700                 :          0 :           switch (bs)
    2701                 :            :             {
    2702                 :          0 :             case 32:
    2703                 :          0 :               imm->m_type = BRIG_TYPE_U8X4;
    2704                 :          0 :               break;
    2705                 :          0 :             case 64:
    2706                 :          0 :               imm->m_type = BRIG_TYPE_U8X8;
    2707                 :          0 :               break;
    2708                 :          0 :             case 128:
    2709                 :          0 :               imm->m_type = BRIG_TYPE_U8X16;
    2710                 :          0 :               break;
    2711                 :          0 :             default:
    2712                 :          0 :               gcc_unreachable ();
    2713                 :            :             }
    2714                 :            :         }
    2715                 :            :     }
    2716                 :            : 
    2717                 :          0 :   hbb->append_insn (mem);
    2718                 :            : }
    2719                 :            : 
    2720                 :            : /* Generate memory copy instructions that are going to be used
    2721                 :            :    for copying a SRC memory to TARGET memory,
    2722                 :            :    represented by pointer in a register.  MIN_ALIGN is minimal alignment
    2723                 :            :    of provided HSA addresses.  */
    2724                 :            : 
    2725                 :            : static void
    2726                 :          0 : gen_hsa_memory_copy (hsa_bb *hbb, hsa_op_address *target, hsa_op_address *src,
    2727                 :            :                      unsigned size, BrigAlignment8_t min_align)
    2728                 :            : {
    2729                 :          0 :   hsa_op_address *addr;
    2730                 :          0 :   hsa_insn_mem *mem;
    2731                 :            : 
    2732                 :          0 :   unsigned offset = 0;
    2733                 :          0 :   unsigned min_byte_align = hsa_byte_alignment (min_align);
    2734                 :            : 
    2735                 :          0 :   while (size)
    2736                 :            :     {
    2737                 :          0 :       unsigned s;
    2738                 :          0 :       if (size >= 8)
    2739                 :            :         s = 8;
    2740                 :          0 :       else if (size >= 4)
    2741                 :            :         s = 4;
    2742                 :          0 :       else if (size >= 2)
    2743                 :            :         s = 2;
    2744                 :            :       else
    2745                 :          0 :         s = 1;
    2746                 :            : 
    2747                 :          0 :       if (s > min_byte_align)
    2748                 :            :         s = min_byte_align;
    2749                 :            : 
    2750                 :          0 :       BrigType16_t t = get_integer_type_by_bytes (s, false);
    2751                 :            : 
    2752                 :          0 :       hsa_op_reg *tmp = new hsa_op_reg (t);
    2753                 :          0 :       addr = new hsa_op_address (src->m_symbol, src->m_reg,
    2754                 :          0 :                                  src->m_imm_offset + offset);
    2755                 :          0 :       mem = new hsa_insn_mem (BRIG_OPCODE_LD, t, tmp, addr);
    2756                 :          0 :       hbb->append_insn (mem);
    2757                 :            : 
    2758                 :          0 :       addr = new hsa_op_address (target->m_symbol, target->m_reg,
    2759                 :          0 :                                  target->m_imm_offset + offset);
    2760                 :          0 :       mem = new hsa_insn_mem (BRIG_OPCODE_ST, t, tmp, addr);
    2761                 :          0 :       hbb->append_insn (mem);
    2762                 :          0 :       offset += s;
    2763                 :          0 :       size -= s;
    2764                 :            :     }
    2765                 :          0 : }
    2766                 :            : 
    2767                 :            : /* Create a memset mask that is created by copying a CONSTANT byte value
    2768                 :            :    to an integer of BYTE_SIZE bytes.  */
    2769                 :            : 
    2770                 :            : static unsigned HOST_WIDE_INT
    2771                 :          0 : build_memset_value (unsigned HOST_WIDE_INT constant, unsigned byte_size)
    2772                 :            : {
    2773                 :          0 :   if (constant == 0)
    2774                 :            :     return 0;
    2775                 :            : 
    2776                 :          0 :   HOST_WIDE_INT v = constant;
    2777                 :            : 
    2778                 :          0 :   for (unsigned i = 1; i < byte_size; i++)
    2779                 :          0 :     v |= constant << (8 * i);
    2780                 :            : 
    2781                 :          0 :   return v;
    2782                 :            : }
    2783                 :            : 
    2784                 :            : /* Generate memory set instructions that are going to be used
    2785                 :            :    for setting a CONSTANT byte value to TARGET memory of SIZE bytes.
    2786                 :            :    MIN_ALIGN is minimal alignment of provided HSA addresses.  */
    2787                 :            : 
    2788                 :            : static void
    2789                 :          0 : gen_hsa_memory_set (hsa_bb *hbb, hsa_op_address *target,
    2790                 :            :                     unsigned HOST_WIDE_INT constant,
    2791                 :            :                     unsigned size, BrigAlignment8_t min_align)
    2792                 :            : {
    2793                 :          0 :   hsa_op_address *addr;
    2794                 :          0 :   hsa_insn_mem *mem;
    2795                 :            : 
    2796                 :          0 :   unsigned offset = 0;
    2797                 :          0 :   unsigned min_byte_align = hsa_byte_alignment (min_align);
    2798                 :            : 
    2799                 :          0 :   while (size)
    2800                 :            :     {
    2801                 :          0 :       unsigned s;
    2802                 :          0 :       if (size >= 8)
    2803                 :            :         s = 8;
    2804                 :          0 :       else if (size >= 4)
    2805                 :            :         s = 4;
    2806                 :          0 :       else if (size >= 2)
    2807                 :            :         s = 2;
    2808                 :            :       else
    2809                 :          0 :         s = 1;
    2810                 :            : 
    2811                 :          0 :       if (s > min_byte_align)
    2812                 :            :         s = min_byte_align;
    2813                 :            : 
    2814                 :          0 :       addr = new hsa_op_address (target->m_symbol, target->m_reg,
    2815                 :          0 :                                  target->m_imm_offset + offset);
    2816                 :            : 
    2817                 :          0 :       BrigType16_t t = get_integer_type_by_bytes (s, false);
    2818                 :          0 :       HOST_WIDE_INT c = build_memset_value (constant, s);
    2819                 :            : 
    2820                 :          0 :       mem = new hsa_insn_mem (BRIG_OPCODE_ST, t, new hsa_op_immed (c, t),
    2821                 :          0 :                               addr);
    2822                 :          0 :       hbb->append_insn (mem);
    2823                 :          0 :       offset += s;
    2824                 :          0 :       size -= s;
    2825                 :            :     }
    2826                 :          0 : }
    2827                 :            : 
    2828                 :            : /* Generate HSAIL instructions for a single assignment
    2829                 :            :    of an empty constructor to an ADDR_LHS.  Constructor is passed as a
    2830                 :            :    tree RHS and all instructions are appended to HBB.  ALIGN is
    2831                 :            :    alignment of the address.  */
    2832                 :            : 
    2833                 :            : void
    2834                 :          0 : gen_hsa_ctor_assignment (hsa_op_address *addr_lhs, tree rhs, hsa_bb *hbb,
    2835                 :            :                          BrigAlignment8_t align)
    2836                 :            : {
    2837                 :          0 :   if (CONSTRUCTOR_NELTS (rhs))
    2838                 :            :     {
    2839                 :          0 :       HSA_SORRY_AT (EXPR_LOCATION (rhs),
    2840                 :            :                     "support for HSA does not implement load from constructor");
    2841                 :          0 :       return;
    2842                 :            :     }
    2843                 :            : 
    2844                 :          0 :   unsigned size = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (rhs)));
    2845                 :          0 :   gen_hsa_memory_set (hbb, addr_lhs, 0, size, align);
    2846                 :            : }
    2847                 :            : 
    2848                 :            : /* Generate HSA instructions for a single assignment of RHS to LHS.
    2849                 :            :    HBB is the basic block they will be appended to.  */
    2850                 :            : 
    2851                 :            : static void
    2852                 :          0 : gen_hsa_insns_for_single_assignment (tree lhs, tree rhs, hsa_bb *hbb)
    2853                 :            : {
    2854                 :          0 :   if (TREE_CODE (lhs) == SSA_NAME)
    2855                 :            :     {
    2856                 :          0 :       hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
    2857                 :          0 :       if (hsa_seen_error ())
    2858                 :            :         return;
    2859                 :            : 
    2860                 :          0 :       gen_hsa_insns_for_load (dest, rhs, TREE_TYPE (lhs), hbb);
    2861                 :            :     }
    2862                 :          0 :   else if (TREE_CODE (rhs) == SSA_NAME
    2863                 :          0 :            || (is_gimple_min_invariant (rhs) && TREE_CODE (rhs) != STRING_CST))
    2864                 :            :     {
    2865                 :            :       /* Store to memory.  */
    2866                 :          0 :       hsa_op_base *src = hsa_reg_or_immed_for_gimple_op (rhs, hbb);
    2867                 :          0 :       if (hsa_seen_error ())
    2868                 :            :         return;
    2869                 :            : 
    2870                 :          0 :       gen_hsa_insns_for_store (lhs, src, hbb);
    2871                 :            :     }
    2872                 :            :   else
    2873                 :            :     {
    2874                 :          0 :       BrigAlignment8_t lhs_align;
    2875                 :          0 :       hsa_op_address *addr_lhs = gen_hsa_addr_with_align (lhs, hbb,
    2876                 :            :                                                           &lhs_align);
    2877                 :            : 
    2878                 :          0 :       if (TREE_CODE (rhs) == CONSTRUCTOR)
    2879                 :          0 :         gen_hsa_ctor_assignment (addr_lhs, rhs, hbb, lhs_align);
    2880                 :            :       else
    2881                 :            :         {
    2882                 :          0 :           BrigAlignment8_t rhs_align;
    2883                 :          0 :           hsa_op_address *addr_rhs = gen_hsa_addr_with_align (rhs, hbb,
    2884                 :            :                                                               &rhs_align);
    2885                 :            : 
    2886                 :          0 :           unsigned size = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (rhs)));
    2887                 :          0 :           gen_hsa_memory_copy (hbb, addr_lhs, addr_rhs, size,
    2888                 :          0 :                                MIN (lhs_align, rhs_align));
    2889                 :            :         }
    2890                 :            :     }
    2891                 :            : }
    2892                 :            : 
    2893                 :            : /* Prepend before INSN a load from spill symbol of SPILL_REG.  Return the
    2894                 :            :    register into which we loaded.  If this required another register to convert
    2895                 :            :    from a B1 type, return it in *PTMP2, otherwise store NULL into it.  We
    2896                 :            :    assume we are out of SSA so the returned register does not have its
    2897                 :            :    definition set.  */
    2898                 :            : 
    2899                 :            : hsa_op_reg *
    2900                 :          0 : hsa_spill_in (hsa_insn_basic *insn, hsa_op_reg *spill_reg, hsa_op_reg **ptmp2)
    2901                 :            : {
    2902                 :          0 :   hsa_symbol *spill_sym = spill_reg->m_spill_sym;
    2903                 :          0 :   hsa_op_reg *reg = new hsa_op_reg (spill_sym->m_type);
    2904                 :          0 :   hsa_op_address *addr = new hsa_op_address (spill_sym);
    2905                 :            : 
    2906                 :          0 :   hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, spill_sym->m_type,
    2907                 :          0 :                                         reg, addr);
    2908                 :          0 :   hsa_insert_insn_before (mem, insn);
    2909                 :            : 
    2910                 :          0 :   *ptmp2 = NULL;
    2911                 :          0 :   if (spill_reg->m_type == BRIG_TYPE_B1)
    2912                 :            :     {
    2913                 :          0 :       hsa_insn_basic *cvtinsn;
    2914                 :          0 :       *ptmp2 = reg;
    2915                 :          0 :       reg = new hsa_op_reg (spill_reg->m_type);
    2916                 :            : 
    2917                 :          0 :       cvtinsn = new hsa_insn_cvt (reg, *ptmp2);
    2918                 :          0 :       hsa_insert_insn_before (cvtinsn, insn);
    2919                 :            :     }
    2920                 :          0 :   return reg;
    2921                 :            : }
    2922                 :            : 
    2923                 :            : /* Append after INSN a store to spill symbol of SPILL_REG.  Return the register
    2924                 :            :    from which we stored.  If this required another register to convert to a B1
    2925                 :            :    type, return it in *PTMP2, otherwise store NULL into it.  We assume we are
    2926                 :            :    out of SSA so the returned register does not have its use updated.  */
    2927                 :            : 
    2928                 :            : hsa_op_reg *
    2929                 :          0 : hsa_spill_out (hsa_insn_basic *insn, hsa_op_reg *spill_reg, hsa_op_reg **ptmp2)
    2930                 :            : {
    2931                 :          0 :   hsa_symbol *spill_sym = spill_reg->m_spill_sym;
    2932                 :          0 :   hsa_op_reg *reg = new hsa_op_reg (spill_sym->m_type);
    2933                 :          0 :   hsa_op_address *addr = new hsa_op_address (spill_sym);
    2934                 :          0 :   hsa_op_reg *returnreg;
    2935                 :            : 
    2936                 :          0 :   *ptmp2 = NULL;
    2937                 :          0 :   returnreg = reg;
    2938                 :          0 :   if (spill_reg->m_type == BRIG_TYPE_B1)
    2939                 :            :     {
    2940                 :          0 :       hsa_insn_basic *cvtinsn;
    2941                 :          0 :       *ptmp2 = new hsa_op_reg (spill_sym->m_type);
    2942                 :          0 :       reg->m_type = spill_reg->m_type;
    2943                 :            : 
    2944                 :          0 :       cvtinsn = new hsa_insn_cvt (*ptmp2, returnreg);
    2945                 :          0 :       hsa_append_insn_after (cvtinsn, insn);
    2946                 :          0 :       insn = cvtinsn;
    2947                 :          0 :       reg = *ptmp2;
    2948                 :            :     }
    2949                 :            : 
    2950                 :          0 :   hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, spill_sym->m_type, reg,
    2951                 :          0 :                                         addr);
    2952                 :          0 :   hsa_append_insn_after (mem, insn);
    2953                 :          0 :   return returnreg;
    2954                 :            : }
    2955                 :            : 
    2956                 :            : /* Generate a comparison instruction that will compare LHS and RHS with
    2957                 :            :    comparison specified by CODE and put result into register DEST.  DEST has to
    2958                 :            :    have its type set already but must not have its definition set yet.
    2959                 :            :    Generated instructions will be added to HBB.  */
    2960                 :            : 
    2961                 :            : static void
    2962                 :          0 : gen_hsa_cmp_insn_from_gimple (enum tree_code code, tree lhs, tree rhs,
    2963                 :            :                               hsa_op_reg *dest, hsa_bb *hbb)
    2964                 :            : {
    2965                 :          0 :   BrigCompareOperation8_t compare;
    2966                 :            : 
    2967                 :          0 :   switch (code)
    2968                 :            :     {
    2969                 :            :     case LT_EXPR:
    2970                 :            :       compare = BRIG_COMPARE_LT;
    2971                 :            :       break;
    2972                 :            :     case LE_EXPR:
    2973                 :            :       compare = BRIG_COMPARE_LE;
    2974                 :            :       break;
    2975                 :            :     case GT_EXPR:
    2976                 :            :       compare = BRIG_COMPARE_GT;
    2977                 :            :       break;
    2978                 :            :     case GE_EXPR:
    2979                 :            :       compare = BRIG_COMPARE_GE;
    2980                 :            :       break;
    2981                 :            :     case EQ_EXPR:
    2982                 :            :       compare = BRIG_COMPARE_EQ;
    2983                 :            :       break;
    2984                 :            :     case NE_EXPR:
    2985                 :            :       compare = BRIG_COMPARE_NE;
    2986                 :            :       break;
    2987                 :            :     case UNORDERED_EXPR:
    2988                 :            :       compare = BRIG_COMPARE_NAN;
    2989                 :            :       break;
    2990                 :            :     case ORDERED_EXPR:
    2991                 :            :       compare = BRIG_COMPARE_NUM;
    2992                 :            :       break;
    2993                 :            :     case UNLT_EXPR:
    2994                 :            :       compare = BRIG_COMPARE_LTU;
    2995                 :            :       break;
    2996                 :            :     case UNLE_EXPR:
    2997                 :            :       compare = BRIG_COMPARE_LEU;
    2998                 :            :       break;
    2999                 :            :     case UNGT_EXPR:
    3000                 :            :       compare = BRIG_COMPARE_GTU;
    3001                 :            :       break;
    3002                 :            :     case UNGE_EXPR:
    3003                 :            :       compare = BRIG_COMPARE_GEU;
    3004                 :            :       break;
    3005                 :            :     case UNEQ_EXPR:
    3006                 :            :       compare = BRIG_COMPARE_EQU;
    3007                 :            :       break;
    3008                 :            :     case LTGT_EXPR:
    3009                 :            :       compare = BRIG_COMPARE_NEU;
    3010                 :            :       break;
    3011                 :            : 
    3012                 :          0 :     default:
    3013                 :          0 :       HSA_SORRY_ATV (EXPR_LOCATION (lhs),
    3014                 :            :                      "support for HSA does not implement comparison tree "
    3015                 :            :                      "code %s", get_tree_code_name (code));
    3016                 :          0 :       return;
    3017                 :            :     }
    3018                 :            : 
    3019                 :            :   /* CMP instruction returns e.g. 0xffffffff (for a 32-bit with integer)
    3020                 :            :      as a result of comparison.  */
    3021                 :            : 
    3022                 :          0 :   BrigType16_t dest_type = hsa_type_integer_p (dest->m_type)
    3023                 :          0 :     ? (BrigType16_t) BRIG_TYPE_B1 : dest->m_type;
    3024                 :            : 
    3025                 :          0 :   hsa_insn_cmp *cmp = new hsa_insn_cmp (compare, dest_type);
    3026                 :          0 :   hsa_op_with_type *op1 = hsa_reg_or_immed_for_gimple_op (lhs, hbb);
    3027                 :          0 :   cmp->set_op (1, op1->extend_int_to_32bit (hbb));
    3028                 :          0 :   hsa_op_with_type *op2 = hsa_reg_or_immed_for_gimple_op (rhs, hbb);
    3029                 :          0 :   cmp->set_op (2, op2->extend_int_to_32bit (hbb));
    3030                 :            : 
    3031                 :          0 :   hbb->append_insn (cmp);
    3032                 :          0 :   cmp->set_output_in_type (dest, 0, hbb);
    3033                 :            : }
    3034                 :            : 
    3035                 :            : /* Generate an unary instruction with OPCODE and append it to a basic block
    3036                 :            :    HBB.  The instruction uses DEST as a destination and OP1
    3037                 :            :    as a single operand.  */
    3038                 :            : 
    3039                 :            : static void
    3040                 :          0 : gen_hsa_unary_operation (BrigOpcode opcode, hsa_op_reg *dest,
    3041                 :            :                          hsa_op_with_type *op1, hsa_bb *hbb)
    3042                 :            : {
    3043                 :          0 :   gcc_checking_assert (dest);
    3044                 :          0 :   hsa_insn_basic *insn;
    3045                 :            : 
    3046                 :          0 :   if (opcode == BRIG_OPCODE_MOV && hsa_needs_cvt (dest->m_type, op1->m_type))
    3047                 :            :     {
    3048                 :          0 :       insn = new hsa_insn_cvt (dest, op1);
    3049                 :          0 :       hbb->append_insn (insn);
    3050                 :          0 :       return;
    3051                 :            :     }
    3052                 :            : 
    3053                 :          0 :   op1 = op1->extend_int_to_32bit (hbb);
    3054                 :          0 :   if (opcode == BRIG_OPCODE_FIRSTBIT || opcode == BRIG_OPCODE_LASTBIT)
    3055                 :            :     {
    3056                 :          0 :       BrigType16_t srctype = hsa_type_integer_p (op1->m_type) ? op1->m_type
    3057                 :          0 :         : hsa_unsigned_type_for_type (op1->m_type);
    3058                 :          0 :       insn = new hsa_insn_srctype (2, opcode, BRIG_TYPE_U32, srctype, NULL,
    3059                 :          0 :                                    op1);
    3060                 :            :     }
    3061                 :            :   else
    3062                 :            :     {
    3063                 :          0 :       BrigType16_t optype = hsa_extend_inttype_to_32bit (dest->m_type);
    3064                 :          0 :       insn = new hsa_insn_basic (2, opcode, optype, NULL, op1);
    3065                 :            : 
    3066                 :          0 :       if (opcode == BRIG_OPCODE_MOV)
    3067                 :          0 :         hsa_fixup_mov_insn_type (insn);
    3068                 :          0 :       else if (opcode == BRIG_OPCODE_ABS || opcode == BRIG_OPCODE_NEG)
    3069                 :            :         {
    3070                 :            :           /* ABS and NEG only exist in _s form :-/  */
    3071                 :          0 :           if (insn->m_type == BRIG_TYPE_U32)
    3072                 :          0 :             insn->m_type = BRIG_TYPE_S32;
    3073                 :          0 :           else if (insn->m_type == BRIG_TYPE_U64)
    3074                 :          0 :             insn->m_type = BRIG_TYPE_S64;
    3075                 :            :         }
    3076                 :            :     }
    3077                 :            : 
    3078                 :          0 :   hbb->append_insn (insn);
    3079                 :          0 :   insn->set_output_in_type (dest, 0, hbb);
    3080                 :            : }
    3081                 :            : 
    3082                 :            : /* Generate a binary instruction with OPCODE and append it to a basic block
    3083                 :            :    HBB.  The instruction uses DEST as a destination and operands OP1
    3084                 :            :    and OP2.  */
    3085                 :            : 
    3086                 :            : static void
    3087                 :          0 : gen_hsa_binary_operation (int opcode, hsa_op_reg *dest,
    3088                 :            :                           hsa_op_with_type *op1, hsa_op_with_type *op2,
    3089                 :            :                           hsa_bb *hbb)
    3090                 :            : {
    3091                 :          0 :   gcc_checking_assert (dest);
    3092                 :            : 
    3093                 :          0 :   BrigType16_t optype = hsa_extend_inttype_to_32bit (dest->m_type);
    3094                 :          0 :   op1 = op1->extend_int_to_32bit (hbb);
    3095                 :          0 :   op2 = op2->extend_int_to_32bit (hbb);
    3096                 :            : 
    3097                 :          0 :   if ((opcode == BRIG_OPCODE_SHL || opcode == BRIG_OPCODE_SHR)
    3098                 :          0 :       && is_a <hsa_op_immed *> (op2))
    3099                 :            :     {
    3100                 :          0 :       hsa_op_immed *i = dyn_cast <hsa_op_immed *> (op2);
    3101                 :          0 :       i->set_type (BRIG_TYPE_U32);
    3102                 :            :     }
    3103                 :          0 :   if ((opcode == BRIG_OPCODE_OR
    3104                 :          0 :        || opcode == BRIG_OPCODE_XOR
    3105                 :          0 :        || opcode == BRIG_OPCODE_AND)
    3106                 :          0 :       && is_a <hsa_op_immed *> (op2))
    3107                 :            :     {
    3108                 :          0 :       hsa_op_immed *i = dyn_cast <hsa_op_immed *> (op2);
    3109                 :          0 :       i->set_type (hsa_unsigned_type_for_type (i->m_type));
    3110                 :            :     }
    3111                 :            : 
    3112                 :          0 :   hsa_insn_basic *insn = new hsa_insn_basic (3, opcode, optype, NULL,
    3113                 :          0 :                                              op1, op2);
    3114                 :          0 :   hbb->append_insn (insn);
    3115                 :          0 :   insn->set_output_in_type (dest, 0, hbb);
    3116                 :          0 : }
    3117                 :            : 
    3118                 :            : /* Generate HSA instructions for a single assignment.  HBB is the basic block
    3119                 :            :    they will be appended to.  */
    3120                 :            : 
    3121                 :            : static void
    3122                 :          0 : gen_hsa_insns_for_operation_assignment (gimple *assign, hsa_bb *hbb)
    3123                 :            : {
    3124                 :          0 :   tree_code code = gimple_assign_rhs_code (assign);
    3125                 :          0 :   gimple_rhs_class rhs_class = get_gimple_rhs_class (gimple_expr_code (assign));
    3126                 :            : 
    3127                 :          0 :   tree lhs = gimple_assign_lhs (assign);
    3128                 :          0 :   tree rhs1 = gimple_assign_rhs1 (assign);
    3129                 :          0 :   tree rhs2 = gimple_assign_rhs2 (assign);
    3130                 :          0 :   tree rhs3 = gimple_assign_rhs3 (assign);
    3131                 :            : 
    3132                 :          0 :   BrigOpcode opcode;
    3133                 :            : 
    3134                 :          0 :   switch (code)
    3135                 :            :     {
    3136                 :            :     CASE_CONVERT:
    3137                 :            :     case FLOAT_EXPR:
    3138                 :            :       /* The opcode is changed to BRIG_OPCODE_CVT if BRIG types
    3139                 :            :          needs a conversion.  */
    3140                 :            :       opcode = BRIG_OPCODE_MOV;
    3141                 :            :       break;
    3142                 :            : 
    3143                 :          0 :     case PLUS_EXPR:
    3144                 :          0 :     case POINTER_PLUS_EXPR:
    3145                 :          0 :       opcode = BRIG_OPCODE_ADD;
    3146                 :          0 :       break;
    3147                 :          0 :     case MINUS_EXPR:
    3148                 :          0 :       opcode = BRIG_OPCODE_SUB;
    3149                 :          0 :       break;
    3150                 :          0 :     case MULT_EXPR:
    3151                 :          0 :       opcode = BRIG_OPCODE_MUL;
    3152                 :          0 :       break;
    3153                 :          0 :     case MULT_HIGHPART_EXPR:
    3154                 :          0 :       opcode = BRIG_OPCODE_MULHI;
    3155                 :          0 :       break;
    3156                 :          0 :     case RDIV_EXPR:
    3157                 :          0 :     case TRUNC_DIV_EXPR:
    3158                 :          0 :     case EXACT_DIV_EXPR:
    3159                 :          0 :       opcode = BRIG_OPCODE_DIV;
    3160                 :          0 :       break;
    3161                 :          0 :     case CEIL_DIV_EXPR:
    3162                 :          0 :     case FLOOR_DIV_EXPR:
    3163                 :          0 :     case ROUND_DIV_EXPR:
    3164                 :          0 :       HSA_SORRY_AT (gimple_location (assign),
    3165                 :            :                     "support for HSA does not implement %<CEIL_DIV_EXPR%>, "
    3166                 :            :                     "%<FLOOR_DIV_EXPR%> or %<ROUND_DIV_EXPR%>");
    3167                 :          0 :       return;
    3168                 :          0 :     case TRUNC_MOD_EXPR:
    3169                 :          0 :       opcode = BRIG_OPCODE_REM;
    3170                 :          0 :       break;
    3171                 :          0 :     case CEIL_MOD_EXPR:
    3172                 :          0 :     case FLOOR_MOD_EXPR:
    3173                 :          0 :     case ROUND_MOD_EXPR:
    3174                 :          0 :       HSA_SORRY_AT (gimple_location (assign),
    3175                 :            :                     "support for HSA does not implement %<CEIL_MOD_EXPR%>, "
    3176                 :            :                     "%<FLOOR_MOD_EXPR%> or %<ROUND_MOD_EXPR%>");
    3177                 :          0 :       return;
    3178                 :          0 :     case NEGATE_EXPR:
    3179                 :          0 :       opcode = BRIG_OPCODE_NEG;
    3180                 :          0 :       break;
    3181                 :          0 :     case MIN_EXPR:
    3182                 :          0 :       opcode = BRIG_OPCODE_MIN;
    3183                 :          0 :       break;
    3184                 :          0 :     case MAX_EXPR:
    3185                 :          0 :       opcode = BRIG_OPCODE_MAX;
    3186                 :          0 :       break;
    3187                 :          0 :     case ABS_EXPR:
    3188                 :          0 :       opcode = BRIG_OPCODE_ABS;
    3189                 :          0 :       break;
    3190                 :          0 :     case LSHIFT_EXPR:
    3191                 :          0 :       opcode = BRIG_OPCODE_SHL;
    3192                 :          0 :       break;
    3193                 :          0 :     case RSHIFT_EXPR:
    3194                 :          0 :       opcode = BRIG_OPCODE_SHR;
    3195                 :          0 :       break;
    3196                 :          0 :     case LROTATE_EXPR:
    3197                 :          0 :     case RROTATE_EXPR:
    3198                 :          0 :       {
    3199                 :          0 :         hsa_insn_basic *insn = NULL;
    3200                 :          0 :         int code1 = code == LROTATE_EXPR ? BRIG_OPCODE_SHL : BRIG_OPCODE_SHR;
    3201                 :          0 :         int code2 = code != LROTATE_EXPR ? BRIG_OPCODE_SHL : BRIG_OPCODE_SHR;
    3202                 :          0 :         BrigType16_t btype = hsa_type_for_scalar_tree_type (TREE_TYPE (lhs),
    3203                 :            :                                                             true);
    3204                 :            : 
    3205                 :          0 :         hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
    3206                 :          0 :         hsa_op_reg *op1 = new hsa_op_reg (btype);
    3207                 :          0 :         hsa_op_reg *op2 = new hsa_op_reg (btype);
    3208                 :          0 :         hsa_op_with_type *shift1 = hsa_reg_or_immed_for_gimple_op (rhs2, hbb);
    3209                 :            : 
    3210                 :          0 :         tree type = TREE_TYPE (rhs2);
    3211                 :          0 :         unsigned HOST_WIDE_INT bitsize = TREE_INT_CST_LOW (TYPE_SIZE (type));
    3212                 :            : 
    3213                 :          0 :         hsa_op_with_type *shift2 = NULL;
    3214                 :          0 :         if (TREE_CODE (rhs2) == INTEGER_CST)
    3215                 :          0 :           shift2 = new hsa_op_immed (bitsize - tree_to_uhwi (rhs2),
    3216                 :          0 :                                      BRIG_TYPE_U32);
    3217                 :          0 :         else if (TREE_CODE (rhs2) == SSA_NAME)
    3218                 :            :           {
    3219                 :          0 :             hsa_op_reg *s = hsa_cfun->reg_for_gimple_ssa (rhs2);
    3220                 :          0 :             s = as_a <hsa_op_reg *> (s->extend_int_to_32bit (hbb));
    3221                 :          0 :             hsa_op_reg *d = new hsa_op_reg (s->m_type);
    3222                 :          0 :             hsa_op_immed *size_imm = new hsa_op_immed (bitsize, BRIG_TYPE_U32);
    3223                 :            : 
    3224                 :          0 :             insn = new hsa_insn_basic (3, BRIG_OPCODE_SUB, d->m_type,
    3225                 :          0 :                                        d, s, size_imm);
    3226                 :          0 :             hbb->append_insn (insn);
    3227                 :            : 
    3228                 :          0 :             shift2 = d;
    3229                 :            :           }
    3230                 :            :         else
    3231                 :          0 :           gcc_unreachable ();
    3232                 :            : 
    3233                 :          0 :         hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
    3234                 :          0 :         gen_hsa_binary_operation (code1, op1, src, shift1, hbb);
    3235                 :          0 :         gen_hsa_binary_operation (code2, op2, src, shift2, hbb);
    3236                 :          0 :         gen_hsa_binary_operation (BRIG_OPCODE_OR, dest, op1, op2, hbb);
    3237                 :            : 
    3238                 :          0 :         return;
    3239                 :            :       }
    3240                 :          0 :     case BIT_IOR_EXPR:
    3241                 :          0 :       opcode = BRIG_OPCODE_OR;
    3242                 :          0 :       break;
    3243                 :          0 :     case BIT_XOR_EXPR:
    3244                 :          0 :       opcode = BRIG_OPCODE_XOR;
    3245                 :          0 :       break;
    3246                 :          0 :     case BIT_AND_EXPR:
    3247                 :          0 :       opcode = BRIG_OPCODE_AND;
    3248                 :          0 :       break;
    3249                 :          0 :     case BIT_NOT_EXPR:
    3250                 :          0 :       opcode = BRIG_OPCODE_NOT;
    3251                 :          0 :       break;
    3252                 :          0 :     case FIX_TRUNC_EXPR:
    3253                 :          0 :       {
    3254                 :          0 :         hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
    3255                 :          0 :         hsa_op_with_type *v = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
    3256                 :            : 
    3257                 :          0 :         if (hsa_needs_cvt (dest->m_type, v->m_type))
    3258                 :            :           {
    3259                 :          0 :             hsa_op_reg *tmp = new hsa_op_reg (v->m_type);
    3260                 :            : 
    3261                 :          0 :             hsa_insn_basic *insn = new hsa_insn_basic (2, BRIG_OPCODE_TRUNC,
    3262                 :          0 :                                                        tmp->m_type, tmp, v);
    3263                 :          0 :             hbb->append_insn (insn);
    3264                 :            : 
    3265                 :          0 :             hsa_insn_basic *cvtinsn = new hsa_insn_cvt (dest, tmp);
    3266                 :          0 :             hbb->append_insn (cvtinsn);
    3267                 :            :           }
    3268                 :            :         else
    3269                 :            :           {
    3270                 :          0 :             hsa_insn_basic *insn = new hsa_insn_basic (2, BRIG_OPCODE_TRUNC,
    3271                 :          0 :                                                        dest->m_type, dest, v);
    3272                 :          0 :             hbb->append_insn (insn);
    3273                 :            :           }
    3274                 :            : 
    3275                 :            :         return;
    3276                 :            :       }
    3277                 :            :       opcode = BRIG_OPCODE_TRUNC;
    3278                 :            :       break;
    3279                 :            : 
    3280                 :          0 :     case LT_EXPR:
    3281                 :          0 :     case LE_EXPR:
    3282                 :          0 :     case GT_EXPR:
    3283                 :          0 :     case GE_EXPR:
    3284                 :          0 :     case EQ_EXPR:
    3285                 :          0 :     case NE_EXPR:
    3286                 :          0 :     case UNORDERED_EXPR:
    3287                 :          0 :     case ORDERED_EXPR:
    3288                 :          0 :     case UNLT_EXPR:
    3289                 :          0 :     case UNLE_EXPR:
    3290                 :          0 :     case UNGT_EXPR:
    3291                 :          0 :     case UNGE_EXPR:
    3292                 :          0 :     case UNEQ_EXPR:
    3293                 :          0 :     case LTGT_EXPR:
    3294                 :          0 :       {
    3295                 :          0 :         hsa_op_reg *dest
    3296                 :          0 :           = hsa_cfun->reg_for_gimple_ssa (gimple_assign_lhs (assign));
    3297                 :            : 
    3298                 :          0 :         gen_hsa_cmp_insn_from_gimple (code, rhs1, rhs2, dest, hbb);
    3299                 :          0 :         return;
    3300                 :            :       }
    3301                 :          0 :     case COND_EXPR:
    3302                 :          0 :       {
    3303                 :          0 :         hsa_op_reg *dest
    3304                 :          0 :           = hsa_cfun->reg_for_gimple_ssa (gimple_assign_lhs (assign));
    3305                 :          0 :         hsa_op_with_type *ctrl = NULL;
    3306                 :          0 :         tree cond = rhs1;
    3307                 :            : 
    3308                 :          0 :         if (CONSTANT_CLASS_P (cond) || TREE_CODE (cond) == SSA_NAME)
    3309                 :          0 :           ctrl = hsa_reg_or_immed_for_gimple_op (cond, hbb);
    3310                 :            :         else
    3311                 :            :           {
    3312                 :          0 :             hsa_op_reg *r = new hsa_op_reg (BRIG_TYPE_B1);
    3313                 :            : 
    3314                 :          0 :             gen_hsa_cmp_insn_from_gimple (TREE_CODE (cond),
    3315                 :          0 :                                   TREE_OPERAND (cond, 0),
    3316                 :          0 :                                   TREE_OPERAND (cond, 1),
    3317                 :            :                                   r, hbb);
    3318                 :            : 
    3319                 :          0 :             ctrl = r;
    3320                 :            :           }
    3321                 :            : 
    3322                 :          0 :         hsa_op_with_type *op2 = hsa_reg_or_immed_for_gimple_op (rhs2, hbb);
    3323                 :          0 :         hsa_op_with_type *op3 = hsa_reg_or_immed_for_gimple_op (rhs3, hbb);
    3324                 :          0 :         op2 = op2->extend_int_to_32bit (hbb);
    3325                 :          0 :         op3 = op3->extend_int_to_32bit (hbb);
    3326                 :            : 
    3327                 :          0 :         BrigType16_t type = hsa_extend_inttype_to_32bit (dest->m_type);
    3328                 :          0 :         BrigType16_t utype = hsa_unsigned_type_for_type (type);
    3329                 :          0 :         if (is_a <hsa_op_immed *> (op2))
    3330                 :          0 :           op2->m_type = utype;
    3331                 :          0 :         if (is_a <hsa_op_immed *> (op3))
    3332                 :          0 :           op3->m_type = utype;
    3333                 :            : 
    3334                 :          0 :         hsa_insn_basic *insn
    3335                 :            :           = new hsa_insn_basic (4, BRIG_OPCODE_CMOV,
    3336                 :          0 :                                 hsa_bittype_for_type (type),
    3337                 :          0 :                                 NULL, ctrl, op2, op3);
    3338                 :            : 
    3339                 :          0 :         hbb->append_insn (insn);
    3340                 :          0 :         insn->set_output_in_type (dest, 0, hbb);
    3341                 :          0 :         return;
    3342                 :            :       }
    3343                 :          0 :     case COMPLEX_EXPR:
    3344                 :          0 :       {
    3345                 :          0 :         hsa_op_reg *dest
    3346                 :          0 :           = hsa_cfun->reg_for_gimple_ssa (gimple_assign_lhs (assign));
    3347                 :          0 :         hsa_op_with_type *rhs1_reg = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
    3348                 :          0 :         rhs1_reg = rhs1_reg->extend_int_to_32bit (hbb);
    3349                 :          0 :         hsa_op_with_type *rhs2_reg = hsa_reg_or_immed_for_gimple_op (rhs2, hbb);
    3350                 :          0 :         rhs2_reg = rhs2_reg->extend_int_to_32bit (hbb);
    3351                 :            : 
    3352                 :          0 :         if (hsa_seen_error ())
    3353                 :            :           return;
    3354                 :            : 
    3355                 :          0 :         BrigType16_t src_type = hsa_bittype_for_type (rhs1_reg->m_type);
    3356                 :          0 :         rhs1_reg = rhs1_reg->get_in_type (src_type, hbb);
    3357                 :          0 :         rhs2_reg = rhs2_reg->get_in_type (src_type, hbb);
    3358                 :            : 
    3359                 :          0 :         hsa_insn_packed *insn
    3360                 :          0 :           = new hsa_insn_packed (3, BRIG_OPCODE_COMBINE, dest->m_type, src_type,
    3361                 :          0 :                                  dest, rhs1_reg, rhs2_reg);
    3362                 :          0 :         hbb->append_insn (insn);
    3363                 :            : 
    3364                 :          0 :         return;
    3365                 :            :       }
    3366                 :          0 :     default:
    3367                 :            :       /* Implement others as we come across them.  */
    3368                 :          0 :       HSA_SORRY_ATV (gimple_location (assign),
    3369                 :            :                      "support for HSA does not implement operation %s",
    3370                 :            :                      get_tree_code_name (code));
    3371                 :          0 :       return;
    3372                 :            :     }
    3373                 :            : 
    3374                 :            : 
    3375                 :          0 :   hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
    3376                 :          0 :   hsa_op_with_type *op1 = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
    3377                 :          0 :   hsa_op_with_type *op2
    3378                 :          0 :     = rhs2 ? hsa_reg_or_immed_for_gimple_op (rhs2, hbb) : NULL;
    3379                 :            : 
    3380                 :          0 :   if (hsa_seen_error ())
    3381                 :            :     return;
    3382                 :            : 
    3383                 :          0 :   switch (rhs_class)
    3384                 :            :     {
    3385                 :          0 :     case GIMPLE_TERNARY_RHS:
    3386                 :          0 :       {
    3387                 :          0 :         hsa_op_with_type *op3 = hsa_reg_or_immed_for_gimple_op (rhs3, hbb);
    3388                 :          0 :         op3 = op3->extend_int_to_32bit (hbb);
    3389                 :          0 :         hsa_insn_basic *insn = new hsa_insn_basic (4, opcode, dest->m_type, dest,
    3390                 :          0 :                                                    op1, op2, op3);
    3391                 :          0 :         hbb->append_insn (insn);
    3392                 :            :       }
    3393                 :          0 :       return;
    3394                 :            : 
    3395                 :          0 :     case GIMPLE_BINARY_RHS:
    3396                 :          0 :       gen_hsa_binary_operation (opcode, dest, op1, op2, hbb);
    3397                 :          0 :       break;
    3398                 :            : 
    3399                 :          0 :     case GIMPLE_UNARY_RHS:
    3400                 :          0 :       gen_hsa_unary_operation (opcode, dest, op1, hbb);
    3401                 :          0 :       break;
    3402                 :          0 :     default:
    3403                 :          0 :       gcc_unreachable ();
    3404                 :            :     }
    3405                 :            : }
    3406                 :            : 
    3407                 :            : /* Generate HSA instructions for a given gimple condition statement COND.
    3408                 :            :    Instructions will be appended to HBB, which also needs to be the
    3409                 :            :    corresponding structure to the basic_block of COND.  */
    3410                 :            : 
    3411                 :            : static void
    3412                 :          0 : gen_hsa_insns_for_cond_stmt (gimple *cond, hsa_bb *hbb)
    3413                 :            : {
    3414                 :          0 :   hsa_op_reg *ctrl = new hsa_op_reg (BRIG_TYPE_B1);
    3415                 :          0 :   hsa_insn_cbr *cbr;
    3416                 :            : 
    3417                 :          0 :   gen_hsa_cmp_insn_from_gimple (gimple_cond_code (cond),
    3418                 :            :                                 gimple_cond_lhs (cond),
    3419                 :            :                                 gimple_cond_rhs (cond),
    3420                 :            :                                 ctrl, hbb);
    3421                 :            : 
    3422                 :          0 :   cbr = new hsa_insn_cbr (ctrl);
    3423                 :          0 :   hbb->append_insn (cbr);
    3424                 :          0 : }
    3425                 :            : 
    3426                 :            : /* Maximum number of elements in a jump table for an HSA SBR instruction.  */
    3427                 :            : 
    3428                 :            : #define HSA_MAXIMUM_SBR_LABELS  16
    3429                 :            : 
    3430                 :            : /* Return lowest value of a switch S that is handled in a non-default
    3431                 :            :    label.  */
    3432                 :            : 
    3433                 :            : static tree
    3434                 :          0 : get_switch_low (gswitch *s)
    3435                 :            : {
    3436                 :          0 :   unsigned labels = gimple_switch_num_labels (s);
    3437                 :          0 :   gcc_checking_assert (labels >= 1);
    3438                 :            : 
    3439                 :          0 :   return CASE_LOW (gimple_switch_label (s, 1));
    3440                 :            : }
    3441                 :            : 
    3442                 :            : /* Return highest value of a switch S that is handled in a non-default
    3443                 :            :    label.  */
    3444                 :            : 
    3445                 :            : static tree
    3446                 :          0 : get_switch_high (gswitch *s)
    3447                 :            : {
    3448                 :          0 :   unsigned labels = gimple_switch_num_labels (s);
    3449                 :            : 
    3450                 :            :   /* Compare last label to maximum number of labels.  */
    3451                 :          0 :   tree label = gimple_switch_label (s, labels - 1);
    3452                 :          0 :   tree low = CASE_LOW (label);
    3453                 :          0 :   tree high = CASE_HIGH (label);
    3454                 :            : 
    3455                 :          0 :   return high != NULL_TREE ? high : low;
    3456                 :            : }
    3457                 :            : 
    3458                 :            : static tree
    3459                 :          0 : get_switch_size (gswitch *s)
    3460                 :            : {
    3461                 :          0 :   return int_const_binop (MINUS_EXPR, get_switch_high (s), get_switch_low (s));
    3462                 :            : }
    3463                 :            : 
    3464                 :            : /* Generate HSA instructions for a given gimple switch.
    3465                 :            :    Instructions will be appended to HBB.  */
    3466                 :            : 
    3467                 :            : static void
    3468                 :          0 : gen_hsa_insns_for_switch_stmt (gswitch *s, hsa_bb *hbb)
    3469                 :            : {
    3470                 :          0 :   gimple_stmt_iterator it = gsi_for_stmt (s);
    3471                 :          0 :   gsi_prev (&it);
    3472                 :            : 
    3473                 :            :   /* Create preambule that verifies that index - lowest_label >= 0.  */
    3474                 :          0 :   edge e = split_block (hbb->m_bb, gsi_stmt (it));
    3475                 :          0 :   e->flags &= ~EDGE_FALLTHRU;
    3476                 :          0 :   e->flags |= EDGE_TRUE_VALUE;
    3477                 :            : 
    3478                 :          0 :   tree index_tree = gimple_switch_index (s);
    3479                 :          0 :   tree lowest = get_switch_low (s);
    3480                 :          0 :   tree highest = get_switch_high (s);
    3481                 :            : 
    3482                 :          0 :   hsa_op_reg *index = hsa_cfun->reg_for_gimple_ssa (index_tree);
    3483                 :          0 :   index = as_a <hsa_op_reg *> (index->extend_int_to_32bit (hbb));
    3484                 :            : 
    3485                 :          0 :   hsa_op_reg *cmp1_reg = new hsa_op_reg (BRIG_TYPE_B1);
    3486                 :          0 :   hsa_op_immed *cmp1_immed = new hsa_op_immed (lowest, true);
    3487                 :          0 :   hbb->append_insn (new hsa_insn_cmp (BRIG_COMPARE_GE, cmp1_reg->m_type,
    3488                 :          0 :                                       cmp1_reg, index, cmp1_immed));
    3489                 :            : 
    3490                 :          0 :   hsa_op_reg *cmp2_reg = new hsa_op_reg (BRIG_TYPE_B1);
    3491                 :          0 :   hsa_op_immed *cmp2_immed = new hsa_op_immed (highest, true);
    3492                 :          0 :   hbb->append_insn (new hsa_insn_cmp (BRIG_COMPARE_LE, cmp2_reg->m_type,
    3493                 :          0 :                                       cmp2_reg, index, cmp2_immed));
    3494                 :            : 
    3495                 :          0 :   hsa_op_reg *cmp_reg = new hsa_op_reg (BRIG_TYPE_B1);
    3496                 :          0 :   hbb->append_insn (new hsa_insn_basic (3, BRIG_OPCODE_AND, cmp_reg->m_type,
    3497                 :          0 :                                         cmp_reg, cmp1_reg, cmp2_reg));
    3498                 :            : 
    3499                 :          0 :   hbb->append_insn (new hsa_insn_cbr (cmp_reg));
    3500                 :            : 
    3501                 :          0 :   basic_block default_label_bb = gimple_switch_default_bb (cfun, s);
    3502                 :            : 
    3503                 :          0 :   if (!gimple_seq_empty_p (phi_nodes (default_label_bb)))
    3504                 :            :     {
    3505                 :          0 :       default_label_bb = split_edge (find_edge (e->dest, default_label_bb));
    3506                 :          0 :       hsa_init_new_bb (default_label_bb);
    3507                 :            :     }
    3508                 :            : 
    3509                 :          0 :   make_edge (e->src, default_label_bb, EDGE_FALSE_VALUE);
    3510                 :            : 
    3511                 :          0 :   hsa_cfun->m_modified_cfg = true;
    3512                 :            : 
    3513                 :            :   /* Basic block with the SBR instruction.  */
    3514                 :          0 :   hbb = hsa_init_new_bb (e->dest);
    3515                 :            : 
    3516                 :          0 :   hsa_op_reg *sub_index = new hsa_op_reg (index->m_type);
    3517                 :          0 :   hbb->append_insn (new hsa_insn_basic (3, BRIG_OPCODE_SUB, sub_index->m_type,
    3518                 :            :                                         sub_index, index,
    3519                 :          0 :                                         new hsa_op_immed (lowest, true)));
    3520                 :            : 
    3521                 :          0 :   hsa_op_base *tmp = sub_index->get_in_type (BRIG_TYPE_U64, hbb);
    3522                 :          0 :   sub_index = as_a <hsa_op_reg *> (tmp);
    3523                 :          0 :   unsigned labels = gimple_switch_num_labels (s);
    3524                 :          0 :   unsigned HOST_WIDE_INT size = tree_to_uhwi (get_switch_size (s));
    3525                 :            : 
    3526                 :          0 :   hsa_insn_sbr *sbr = new hsa_insn_sbr (sub_index, size + 1);
    3527                 :            : 
    3528                 :            :   /* Prepare array with default label destination.  */
    3529                 :          0 :   for (unsigned HOST_WIDE_INT i = 0; i <= size; i++)
    3530                 :          0 :     sbr->m_jump_table.safe_push (default_label_bb);
    3531                 :            : 
    3532                 :            :   /* Iterate all labels and fill up the jump table.  */
    3533                 :          0 :   for (unsigned i = 1; i < labels; i++)
    3534                 :            :     {
    3535                 :          0 :       tree label = gimple_switch_label (s, i);
    3536                 :          0 :       basic_block bb = label_to_block (cfun, CASE_LABEL (label));
    3537                 :            : 
    3538                 :          0 :       unsigned HOST_WIDE_INT sub_low
    3539                 :          0 :         = tree_to_uhwi (int_const_binop (MINUS_EXPR, CASE_LOW (label), lowest));
    3540                 :            : 
    3541                 :          0 :       unsigned HOST_WIDE_INT sub_high = sub_low;
    3542                 :          0 :       tree high = CASE_HIGH (label);
    3543                 :          0 :       if (high != NULL)
    3544                 :          0 :         sub_high = tree_to_uhwi (int_const_binop (MINUS_EXPR, high, lowest));
    3545                 :            : 
    3546                 :          0 :       for (unsigned HOST_WIDE_INT j = sub_low; j <= sub_high; j++)
    3547                 :          0 :         sbr->m_jump_table[j] = bb;
    3548                 :            :     }
    3549                 :            : 
    3550                 :          0 :   hbb->append_insn (sbr);
    3551                 :          0 : }
    3552                 :            : 
    3553                 :            : /* Verify that the function DECL can be handled by HSA.  */
    3554                 :            : 
    3555                 :            : static void
    3556                 :          0 : verify_function_arguments (tree decl)
    3557                 :            : {
    3558                 :          0 :   tree type = TREE_TYPE (decl);
    3559                 :          0 :   if (DECL_STATIC_CHAIN (decl))
    3560                 :            :     {
    3561                 :          0 :       HSA_SORRY_ATV (EXPR_LOCATION (decl),
    3562                 :            :                      "HSA does not support nested functions: %qD", decl);
    3563                 :          0 :       return;
    3564                 :            :     }
    3565                 :          0 :   else if (!TYPE_ARG_TYPES (type) || stdarg_p (type))
    3566                 :            :     {
    3567                 :          0 :       HSA_SORRY_ATV (EXPR_LOCATION (decl),
    3568                 :            :                      "HSA does not support functions with variadic arguments "
    3569                 :            :                      "(or unknown return type): %qD", decl);
    3570                 :          0 :       return;
    3571                 :            :     }
    3572                 :            : }
    3573                 :            : 
    3574                 :            : /* Return BRIG type for FORMAL_ARG_TYPE.  If the formal argument type is NULL,
    3575                 :            :    return ACTUAL_ARG_TYPE.  */
    3576                 :            : 
    3577                 :            : static BrigType16_t
    3578                 :          0 : get_format_argument_type (tree formal_arg_type, BrigType16_t actual_arg_type)
    3579                 :            : {
    3580                 :          0 :   if (formal_arg_type == NULL)
    3581                 :            :     return actual_arg_type;
    3582                 :            : 
    3583                 :          0 :   BrigType16_t decl_type
    3584                 :          0 :     = hsa_type_for_scalar_tree_type (formal_arg_type, false);
    3585                 :          0 :   return mem_type_for_type (decl_type);
    3586                 :            : }
    3587                 :            : 
    3588                 :            : /* Generate HSA instructions for a direct call instruction.
    3589                 :            :    Instructions will be appended to HBB, which also needs to be the
    3590                 :            :    corresponding structure to the basic_block of STMT.
    3591                 :            :    If ASSIGN_LHS is false, do not copy HSA function result argument into the
    3592                 :            :    corresponding HSA representation of the gimple statement LHS.  */
    3593                 :            : 
    3594                 :            : static void
    3595                 :          0 : gen_hsa_insns_for_direct_call (gimple *stmt, hsa_bb *hbb,
    3596                 :            :                                bool assign_lhs = true)
    3597                 :            : {
    3598                 :          0 :   tree decl = gimple_call_fndecl (stmt);
    3599                 :          0 :   verify_function_arguments (decl);
    3600                 :          0 :   if (hsa_seen_error ())
    3601                 :            :     return;
    3602                 :            : 
    3603                 :          0 :   hsa_insn_call *call_insn = new hsa_insn_call (decl);
    3604                 :          0 :   hsa_cfun->m_called_functions.safe_push (call_insn->m_called_function);
    3605                 :            : 
    3606                 :            :   /* Argument block start.  */
    3607                 :          0 :   hsa_insn_arg_block *arg_start
    3608                 :          0 :     = new hsa_insn_arg_block (BRIG_KIND_DIRECTIVE_ARG_BLOCK_START, call_insn);
    3609                 :          0 :   hbb->append_insn (arg_start);
    3610                 :            : 
    3611                 :          0 :   tree parm_type_chain = TYPE_ARG_TYPES (gimple_call_fntype (stmt));
    3612                 :            : 
    3613                 :            :   /* Preparation of arguments that will be passed to function.  */
    3614                 :          0 :   const unsigned args = gimple_call_num_args (stmt);
    3615                 :          0 :   for (unsigned i = 0; i < args; ++i)
    3616                 :            :     {
    3617                 :          0 :       tree parm = gimple_call_arg (stmt, (int)i);
    3618                 :          0 :       tree parm_decl_type = parm_type_chain != NULL_TREE
    3619                 :          0 :         ? TREE_VALUE (parm_type_chain) : NULL_TREE;
    3620                 :          0 :       hsa_op_address *addr;
    3621                 :            : 
    3622                 :          0 :       if (AGGREGATE_TYPE_P (TREE_TYPE (parm)))
    3623                 :            :         {
    3624                 :          0 :           addr = gen_hsa_addr_for_arg (TREE_TYPE (parm), i);
    3625                 :          0 :           BrigAlignment8_t align;
    3626                 :          0 :           hsa_op_address *src = gen_hsa_addr_with_align (parm, hbb, &align);
    3627                 :          0 :           gen_hsa_memory_copy (hbb, addr, src,
    3628                 :          0 :                                addr->m_symbol->total_byte_size (), align);
    3629                 :            :         }
    3630                 :            :       else
    3631                 :            :         {
    3632                 :          0 :           hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (parm, hbb);
    3633                 :            : 
    3634                 :          0 :           if (parm_decl_type != NULL && AGGREGATE_TYPE_P (parm_decl_type))
    3635                 :            :             {
    3636                 :          0 :               HSA_SORRY_AT (gimple_location (stmt),
    3637                 :            :                             "support for HSA does not implement an aggregate "
    3638                 :            :                             "formal argument in a function call, while actual "
    3639                 :            :                             "argument is not an aggregate");
    3640                 :          0 :               return;
    3641                 :            :             }
    3642                 :            : 
    3643                 :          0 :           BrigType16_t formal_arg_type
    3644                 :          0 :             = get_format_argument_type (parm_decl_type, src->m_type);
    3645                 :          0 :           if (hsa_seen_error ())
    3646                 :            :             return;
    3647                 :            : 
    3648                 :          0 :           if (src->m_type != formal_arg_type)
    3649                 :          0 :             src = src->get_in_type (formal_arg_type, hbb);
    3650                 :            : 
    3651                 :          0 :           addr
    3652                 :          0 :             = gen_hsa_addr_for_arg (parm_decl_type != NULL_TREE ?
    3653                 :          0 :                                     parm_decl_type: TREE_TYPE (parm), i);
    3654                 :          0 :           hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, formal_arg_type,
    3655                 :          0 :                                                 src, addr);
    3656                 :            : 
    3657                 :          0 :           hbb->append_insn (mem);
    3658                 :            :         }
    3659                 :            : 
    3660                 :          0 :       call_insn->m_input_args.safe_push (addr->m_symbol);
    3661                 :          0 :       if (parm_type_chain)
    3662                 :          0 :         parm_type_chain = TREE_CHAIN (parm_type_chain);
    3663                 :            :     }
    3664                 :            : 
    3665                 :          0 :   call_insn->m_args_code_list = new hsa_op_code_list (args);
    3666                 :          0 :   hbb->append_insn (call_insn);
    3667                 :            : 
    3668                 :          0 :   tree result_type = TREE_TYPE (TREE_TYPE (decl));
    3669                 :            : 
    3670                 :          0 :   tree result = gimple_call_lhs (stmt);
    3671                 :          0 :   hsa_insn_mem *result_insn = NULL;
    3672                 :          0 :   if (!VOID_TYPE_P (result_type))
    3673                 :            :     {
    3674                 :          0 :       hsa_op_address *addr = gen_hsa_addr_for_arg (result_type, -1);
    3675                 :            : 
    3676                 :            :       /* Even if result of a function call is unused, we have to emit
    3677                 :            :          declaration for the result.  */
    3678                 :          0 :       if (result && assign_lhs)
    3679                 :            :         {
    3680                 :          0 :           tree lhs_type = TREE_TYPE (result);
    3681                 :            : 
    3682                 :          0 :           if (hsa_seen_error ())
    3683                 :            :             return;
    3684                 :            : 
    3685                 :          0 :           if (AGGREGATE_TYPE_P (lhs_type))
    3686                 :            :             {
    3687                 :          0 :               BrigAlignment8_t align;
    3688                 :          0 :               hsa_op_address *result_addr
    3689                 :          0 :                 = gen_hsa_addr_with_align (result, hbb, &align);
    3690                 :          0 :               gen_hsa_memory_copy (hbb, result_addr, addr,
    3691                 :          0 :                                    addr->m_symbol->total_byte_size (), align);
    3692                 :            :             }
    3693                 :            :           else
    3694                 :            :             {
    3695                 :          0 :               BrigType16_t mtype
    3696                 :          0 :                 = mem_type_for_type (hsa_type_for_scalar_tree_type (lhs_type,
    3697                 :            :                                                                     false));
    3698                 :            : 
    3699                 :          0 :               hsa_op_reg *dst = hsa_cfun->reg_for_gimple_ssa (result);
    3700                 :          0 :               result_insn = new hsa_insn_mem (BRIG_OPCODE_LD, mtype, dst, addr);
    3701                 :          0 :               hbb->append_insn (result_insn);
    3702                 :            :             }
    3703                 :            :         }
    3704                 :            : 
    3705                 :          0 :       call_insn->m_output_arg = addr->m_symbol;
    3706                 :          0 :       call_insn->m_result_code_list = new hsa_op_code_list (1);
    3707                 :            :     }
    3708                 :            :   else
    3709                 :            :     {
    3710                 :          0 :       if (result)
    3711                 :            :         {
    3712                 :          0 :           HSA_SORRY_AT (gimple_location (stmt),
    3713                 :            :                         "support for HSA does not implement an assignment of "
    3714                 :            :                         "return value from a void function");
    3715                 :          0 :           return;
    3716                 :            :         }
    3717                 :            : 
    3718                 :          0 :       call_insn->m_result_code_list = new hsa_op_code_list (0);
    3719                 :            :     }
    3720                 :            : 
    3721                 :            :   /* Argument block end.  */
    3722                 :          0 :   hsa_insn_arg_block *arg_end
    3723                 :          0 :     = new hsa_insn_arg_block (BRIG_KIND_DIRECTIVE_ARG_BLOCK_END, call_insn);
    3724                 :          0 :   hbb->append_insn (arg_end);
    3725                 :            : }
    3726                 :            : 
    3727                 :            : /* Generate HSA instructions for a direct call of an internal fn.
    3728                 :            :    Instructions will be appended to HBB, which also needs to be the
    3729                 :            :    corresponding structure to the basic_block of STMT.  */
    3730                 :            : 
    3731                 :            : static void
    3732                 :          0 : gen_hsa_insns_for_call_of_internal_fn (gimple *stmt, hsa_bb *hbb)
    3733                 :            : {
    3734                 :          0 :   tree lhs = gimple_call_lhs (stmt);
    3735                 :          0 :   if (!lhs)
    3736                 :            :     return;
    3737                 :            : 
    3738                 :          0 :   tree lhs_type = TREE_TYPE (lhs);
    3739                 :          0 :   tree rhs1 = gimple_call_arg (stmt, 0);
    3740                 :          0 :   tree rhs1_type = TREE_TYPE (rhs1);
    3741                 :          0 :   enum internal_fn fn = gimple_call_internal_fn (stmt);
    3742                 :          0 :   hsa_internal_fn *ifn
    3743                 :          0 :     = new hsa_internal_fn (fn, tree_to_uhwi (TYPE_SIZE (rhs1_type)));
    3744                 :          0 :   hsa_insn_call *call_insn = new hsa_insn_call (ifn);
    3745                 :            : 
    3746                 :          0 :   gcc_checking_assert (FLOAT_TYPE_P (rhs1_type));
    3747                 :            : 
    3748                 :          0 :   if (!hsa_emitted_internal_decls->find (call_insn->m_called_internal_fn))
    3749                 :          0 :     hsa_cfun->m_called_internal_fns.safe_push (call_insn->m_called_internal_fn);
    3750                 :            : 
    3751                 :          0 :   hsa_insn_arg_block *arg_start
    3752                 :          0 :     = new hsa_insn_arg_block (BRIG_KIND_DIRECTIVE_ARG_BLOCK_START, call_insn);
    3753                 :          0 :   hbb->append_insn (arg_start);
    3754                 :            : 
    3755                 :          0 :   unsigned num_args = gimple_call_num_args (stmt);
    3756                 :            : 
    3757                 :            :   /* Function arguments.  */
    3758                 :          0 :   for (unsigned i = 0; i < num_args; i++)
    3759                 :            :     {
    3760                 :          0 :       tree parm = gimple_call_arg (stmt, (int)i);
    3761                 :          0 :       hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (parm, hbb);
    3762                 :            : 
    3763                 :          0 :       hsa_op_address *addr = gen_hsa_addr_for_arg (TREE_TYPE (parm), i);
    3764                 :          0 :       hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, src->m_type,
    3765                 :          0 :                                             src, addr);
    3766                 :            : 
    3767                 :          0 :       call_insn->m_input_args.safe_push (addr->m_symbol);
    3768                 :          0 :       hbb->append_insn (mem);
    3769                 :            :     }
    3770                 :            : 
    3771                 :          0 :   call_insn->m_args_code_list = new hsa_op_code_list (num_args);
    3772                 :          0 :   hbb->append_insn (call_insn);
    3773                 :            : 
    3774                 :            :   /* Assign returned value.  */
    3775                 :          0 :   hsa_op_address *addr = gen_hsa_addr_for_arg (lhs_type, -1);
    3776                 :            : 
    3777                 :          0 :   call_insn->m_output_arg = addr->m_symbol;
    3778                 :          0 :   call_insn->m_result_code_list = new hsa_op_code_list (1);
    3779                 :            : 
    3780                 :            :   /* Argument block end.  */
    3781                 :          0 :   hsa_insn_arg_block *arg_end
    3782                 :          0 :     = new hsa_insn_arg_block (BRIG_KIND_DIRECTIVE_ARG_BLOCK_END, call_insn);
    3783                 :          0 :   hbb->append_insn (arg_end);
    3784                 :            : }
    3785                 :            : 
    3786                 :            : /* Generate HSA instructions for a return value instruction.
    3787                 :            :    Instructions will be appended to HBB, which also needs to be the
    3788                 :            :    corresponding structure to the basic_block of STMT.  */
    3789                 :            : 
    3790                 :            : static void
    3791                 :          0 : gen_hsa_insns_for_return (greturn *stmt, hsa_bb *hbb)
    3792                 :            : {
    3793                 :          0 :   tree retval = gimple_return_retval (stmt);
    3794                 :          0 :   if (retval)
    3795                 :            :     {
    3796                 :          0 :       hsa_op_address *addr = new hsa_op_address (hsa_cfun->m_output_arg);
    3797                 :            : 
    3798                 :          0 :       if (AGGREGATE_TYPE_P (TREE_TYPE (retval)))
    3799                 :            :         {
    3800                 :          0 :           BrigAlignment8_t align;
    3801                 :          0 :           hsa_op_address *retval_addr = gen_hsa_addr_with_align (retval, hbb,
    3802                 :            :                                                                  &align);
    3803                 :          0 :           gen_hsa_memory_copy (hbb, addr, retval_addr,
    3804                 :          0 :                                hsa_cfun->m_output_arg->total_byte_size (),
    3805                 :            :                                align);
    3806                 :            :         }
    3807                 :            :       else
    3808                 :            :         {
    3809                 :          0 :           BrigType16_t t = hsa_type_for_scalar_tree_type (TREE_TYPE (retval),
    3810                 :            :                                                           false);
    3811                 :          0 :           BrigType16_t mtype = mem_type_for_type (t);
    3812                 :            : 
    3813                 :            :           /* Store of return value.  */
    3814                 :          0 :           hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (retval, hbb);
    3815                 :          0 :           src = src->get_in_type (mtype, hbb);
    3816                 :          0 :           hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, mtype, src,
    3817                 :          0 :                                                 addr);
    3818                 :          0 :           hbb->append_insn (mem);
    3819                 :            :         }
    3820                 :            :     }
    3821                 :            : 
    3822                 :            :   /* HSAIL return instruction emission.  */
    3823                 :          0 :   hsa_insn_basic *ret = new hsa_insn_basic (0, BRIG_OPCODE_RET);
    3824                 :          0 :   hbb->append_insn (ret);
    3825                 :          0 : }
    3826                 :            : 
    3827                 :            : /* Set OP_INDEX-th operand of the instruction to DEST, as the DEST
    3828                 :            :    can have a different type, conversion instructions are possibly
    3829                 :            :    appended to HBB.  */
    3830                 :            : 
    3831                 :            : void
    3832                 :          0 : hsa_insn_basic::set_output_in_type (hsa_op_reg *dest, unsigned op_index,
    3833                 :            :                                     hsa_bb *hbb)
    3834                 :            : {
    3835                 :          0 :   gcc_checking_assert (op_output_p (op_index));
    3836                 :            : 
    3837                 :          0 :   if (dest->m_type == m_type)
    3838                 :            :     {
    3839                 :          0 :       set_op (op_index, dest);
    3840                 :          0 :       return;
    3841                 :            :     }
    3842                 :            : 
    3843                 :          0 :   hsa_insn_basic *insn;
    3844                 :          0 :   hsa_op_reg *tmp;
    3845                 :          0 :   if (hsa_needs_cvt (dest->m_type, m_type))
    3846                 :            :     {
    3847                 :          0 :       tmp = new hsa_op_reg (m_type);
    3848                 :          0 :       insn = new hsa_insn_cvt (dest, tmp);
    3849                 :            :     }
    3850                 :          0 :   else if (hsa_type_bit_size (dest->m_type) == hsa_type_bit_size (m_type))
    3851                 :            :     {
    3852                 :            :       /* When output, HSA registers do not really have types, only sizes, so if
    3853                 :            :          the sizes match, we can use the register directly.  */
    3854                 :          0 :       set_op (op_index, dest);
    3855                 :          0 :       return;
    3856                 :            :     }
    3857                 :            :   else
    3858                 :            :     {
    3859                 :          0 :       tmp = new hsa_op_reg (m_type);
    3860                 :          0 :       insn = new hsa_insn_basic (2, BRIG_OPCODE_MOV, dest->m_type,
    3861                 :          0 :                                  dest, tmp->get_in_type (dest->m_type, hbb));
    3862                 :          0 :       hsa_fixup_mov_insn_type (insn);
    3863                 :            :     }
    3864                 :          0 :   set_op (op_index, tmp);
    3865                 :          0 :   hbb->append_insn (insn);
    3866                 :            : }
    3867                 :            : 
    3868                 :            : /* Generate instruction OPCODE to query a property of HSA grid along the
    3869                 :            :    given DIMENSION.  Store result into DEST and append the instruction to
    3870                 :            :    HBB.  */
    3871                 :            : 
    3872                 :            : static void
    3873                 :          0 : query_hsa_grid_dim (hsa_op_reg *dest, int opcode, hsa_op_immed *dimension,
    3874                 :            :                     hsa_bb *hbb)
    3875                 :            : {
    3876                 :          0 :   hsa_insn_basic *insn = new hsa_insn_basic (2, opcode, BRIG_TYPE_U32, NULL,
    3877                 :          0 :                                              dimension);
    3878                 :          0 :   hbb->append_insn (insn);
    3879                 :          0 :   insn->set_output_in_type (dest, 0, hbb);
    3880                 :          0 : }
    3881                 :            : 
    3882                 :            : /* Generate instruction OPCODE to query a property of HSA grid along the given
    3883                 :            :    dimension which is an immediate in first argument of STMT.  Store result
    3884                 :            :    into the register corresponding to LHS of STMT and append the instruction to
    3885                 :            :    HBB.  */
    3886                 :            : 
    3887                 :            : static void
    3888                 :          0 : query_hsa_grid_dim (gimple *stmt, int opcode, hsa_bb *hbb)
    3889                 :            : {
    3890                 :          0 :   tree lhs = gimple_call_lhs (dyn_cast <gcall *> (stmt));
    3891                 :          0 :   if (lhs == NULL_TREE)
    3892                 :            :     return;
    3893                 :            : 
    3894                 :          0 :   tree arg = gimple_call_arg (stmt, 0);
    3895                 :          0 :   unsigned HOST_WIDE_INT dim = 5;
    3896                 :          0 :   if (tree_fits_uhwi_p (arg))
    3897                 :          0 :     dim = tree_to_uhwi (arg);
    3898                 :          0 :   if (dim > 2)
    3899                 :            :     {
    3900                 :          0 :       HSA_SORRY_AT (gimple_location (stmt),
    3901                 :            :                     "HSA grid query dimension must be immediate constant 0, 1 "
    3902                 :            :                     "or 2");
    3903                 :          0 :       return;
    3904                 :            :     }
    3905                 :            : 
    3906                 :          0 :   hsa_op_immed *hdim = new hsa_op_immed (dim, (BrigKind16_t) BRIG_TYPE_U32);
    3907                 :          0 :   hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
    3908                 :          0 :   query_hsa_grid_dim (dest, opcode, hdim, hbb);
    3909                 :            : }
    3910                 :            : 
    3911                 :            : /* Generate instruction OPCODE to query a property of HSA grid that is
    3912                 :            :    independent of any dimension.  Store result into the register corresponding
    3913                 :            :    to LHS of STMT and append the instruction to HBB.  */
    3914                 :            : 
    3915                 :            : static void
    3916                 :          0 : query_hsa_grid_nodim (gimple *stmt, BrigOpcode16_t opcode, hsa_bb *hbb)
    3917                 :            : {
    3918                 :          0 :   tree lhs = gimple_call_lhs (dyn_cast <gcall *> (stmt));
    3919                 :          0 :   if (lhs == NULL_TREE)
    3920                 :            :     return;
    3921                 :          0 :   hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
    3922                 :          0 :   BrigType16_t brig_type = hsa_unsigned_type_for_type (dest->m_type);
    3923                 :          0 :   hsa_insn_basic *insn = new hsa_insn_basic (1, opcode, brig_type, dest);
    3924                 :          0 :   hbb->append_insn (insn);
    3925                 :            : }
    3926                 :            : 
    3927                 :            : /* Emit instructions that set hsa_num_threads according to provided VALUE.
    3928                 :            :    Instructions are appended to basic block HBB.  */
    3929                 :            : 
    3930                 :            : static void
    3931                 :          0 : gen_set_num_threads (tree value, hsa_bb *hbb)
    3932                 :            : {
    3933                 :          0 :   hbb->append_insn (new hsa_insn_comment ("omp_set_num_threads"));
    3934                 :          0 :   hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (value, hbb);
    3935                 :            : 
    3936                 :          0 :   src = src->get_in_type (hsa_num_threads->m_type, hbb);
    3937                 :          0 :   hsa_op_address *addr = new hsa_op_address (hsa_num_threads);
    3938                 :            : 
    3939                 :          0 :   hsa_insn_basic *basic
    3940                 :          0 :     = new hsa_insn_mem (BRIG_OPCODE_ST, hsa_num_threads->m_type, src, addr);
    3941                 :          0 :   hbb->append_insn (basic);
    3942                 :          0 : }
    3943                 :            : 
    3944                 :            : /* Return byte offset of a FIELD_NAME in GOMP_hsa_kernel_dispatch which
    3945                 :            :    is defined in plugin-hsa.c.  */
    3946                 :            : 
    3947                 :            : static HOST_WIDE_INT
    3948                 :          0 : get_hsa_kernel_dispatch_offset (const char *field_name)
    3949                 :            : {
    3950                 :          0 :   tree *hsa_kernel_dispatch_type = hsa_get_kernel_dispatch_type ();
    3951                 :          0 :   if (*hsa_kernel_dispatch_type == NULL)
    3952                 :            :     {
    3953                 :            :       /* Collection of information needed for a dispatch of a kernel from a
    3954                 :            :          kernel.  Keep in sync with libgomp's plugin-hsa.c.  */
    3955                 :            : 
    3956                 :          0 :       *hsa_kernel_dispatch_type = make_node (RECORD_TYPE);
    3957                 :          0 :       tree id_f1 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
    3958                 :            :                                get_identifier ("queue"), ptr_type_node);
    3959                 :          0 :       DECL_CHAIN (id_f1) = NULL_TREE;
    3960                 :          0 :       tree id_f2 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
    3961                 :            :                                get_identifier ("omp_data_memory"),
    3962                 :            :                                ptr_type_node);
    3963                 :          0 :       DECL_CHAIN (id_f2) = id_f1;
    3964                 :          0 :       tree id_f3 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
    3965                 :            :                                get_identifier ("kernarg_address"),
    3966                 :            :                                ptr_type_node);
    3967                 :          0 :       DECL_CHAIN (id_f3) = id_f2;
    3968                 :          0 :       tree id_f4 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
    3969                 :            :                                get_identifier ("object"),
    3970                 :            :                                uint64_type_node);
    3971                 :          0 :       DECL_CHAIN (id_f4) = id_f3;
    3972                 :          0 :       tree id_f5 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
    3973                 :            :                                get_identifier ("signal"),
    3974                 :            :                                uint64_type_node);
    3975                 :          0 :       DECL_CHAIN (id_f5) = id_f4;
    3976                 :          0 :       tree id_f6 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
    3977                 :            :                                get_identifier ("private_segment_size"),
    3978                 :            :                                uint32_type_node);
    3979                 :          0 :       DECL_CHAIN (id_f6) = id_f5;
    3980                 :          0 :       tree id_f7 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
    3981                 :            :                                get_identifier ("group_segment_size"),
    3982                 :            :                                uint32_type_node);
    3983                 :          0 :       DECL_CHAIN (id_f7) = id_f6;
    3984                 :          0 :       tree id_f8 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
    3985                 :            :                                get_identifier ("kernel_dispatch_count"),
    3986                 :            :                                uint64_type_node);
    3987                 :          0 :       DECL_CHAIN (id_f8) = id_f7;
    3988                 :          0 :       tree id_f9 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
    3989                 :            :                                get_identifier ("debug"),
    3990                 :            :                                uint64_type_node);
    3991                 :          0 :       DECL_CHAIN (id_f9) = id_f8;
    3992                 :          0 :       tree id_f10 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
    3993                 :            :                                 get_identifier ("omp_level"),
    3994                 :            :                                 uint64_type_node);
    3995                 :          0 :       DECL_CHAIN (id_f10) = id_f9;
    3996                 :          0 :       tree id_f11 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
    3997                 :            :                                 get_identifier ("children_dispatches"),
    3998                 :            :                                 ptr_type_node);
    3999                 :          0 :       DECL_CHAIN (id_f11) = id_f10;
    4000                 :          0 :       tree id_f12 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
    4001                 :            :                                get_identifier ("omp_num_threads"),
    4002                 :            :                                uint32_type_node);
    4003                 :          0 :       DECL_CHAIN (id_f12) = id_f11;
    4004                 :            : 
    4005                 :            : 
    4006                 :          0 :       finish_builtin_struct (*hsa_kernel_dispatch_type, "__hsa_kernel_dispatch",
    4007                 :            :                              id_f12, NULL_TREE);
    4008                 :          0 :       TYPE_ARTIFICIAL (*hsa_kernel_dispatch_type) = 1;
    4009                 :            :     }
    4010                 :            : 
    4011                 :          0 :   for (tree chain = TYPE_FIELDS (*hsa_kernel_dispatch_type);
    4012                 :          0 :        chain != NULL_TREE; chain = TREE_CHAIN (chain))
    4013                 :          0 :     if (id_equal (DECL_NAME (chain), field_name))
    4014                 :          0 :       return int_byte_position (chain);
    4015                 :            : 
    4016                 :          0 :   gcc_unreachable ();
    4017                 :            : }
    4018                 :            : 
    4019                 :            : /* Return an HSA register that will contain number of threads for
    4020                 :            :    a future dispatched kernel.  Instructions are added to HBB.  */
    4021                 :            : 
    4022                 :            : static hsa_op_reg *
    4023                 :          0 : gen_num_threads_for_dispatch (hsa_bb *hbb)
    4024                 :            : {
    4025                 :            :   /* Step 1) Assign to number of threads:
    4026                 :            :      MIN (HSA_DEFAULT_NUM_THREADS, hsa_num_threads).  */
    4027                 :          0 :   hsa_op_reg *threads = new hsa_op_reg (hsa_num_threads->m_type);
    4028                 :          0 :   hsa_op_address *addr = new hsa_op_address (hsa_num_threads);
    4029                 :            : 
    4030                 :          0 :   hbb->append_insn (new hsa_insn_mem (BRIG_OPCODE_LD, threads->m_type,
    4031                 :          0 :                                       threads, addr));
    4032                 :            : 
    4033                 :          0 :   hsa_op_immed *limit = new hsa_op_immed (HSA_DEFAULT_NUM_THREADS,
    4034                 :          0 :                                           BRIG_TYPE_U32);
    4035                 :          0 :   hsa_op_reg *r = new hsa_op_reg (BRIG_TYPE_B1);
    4036                 :          0 :   hsa_insn_cmp * cmp
    4037                 :          0 :     = new hsa_insn_cmp (BRIG_COMPARE_LT, r->m_type, r, threads, limit);
    4038                 :          0 :   hbb->append_insn (cmp);
    4039                 :            : 
    4040                 :          0 :   BrigType16_t btype = hsa_bittype_for_type (threads->m_type);
    4041                 :          0 :   hsa_op_reg *tmp = new hsa_op_reg (threads->m_type);
    4042                 :            : 
    4043                 :          0 :   hbb->append_insn (new hsa_insn_basic (4, BRIG_OPCODE_CMOV, btype, tmp, r,
    4044                 :          0 :                                         threads, limit));
    4045                 :            : 
    4046                 :            :   /* Step 2) If the number is equal to zero,
    4047                 :            :      return shadow->omp_num_threads.  */
    4048                 :          0 :   hsa_op_reg *shadow_reg_ptr = hsa_cfun->get_shadow_reg ();
    4049                 :            : 
    4050                 :          0 :   hsa_op_reg *shadow_thread_count = new hsa_op_reg (BRIG_TYPE_U32);
    4051                 :          0 :   addr
    4052                 :          0 :     = new hsa_op_address (shadow_reg_ptr,
    4053                 :          0 :                           get_hsa_kernel_dispatch_offset ("omp_num_threads"));
    4054                 :          0 :   hsa_insn_basic *basic
    4055                 :          0 :     = new hsa_insn_mem (BRIG_OPCODE_LD, shadow_thread_count->m_type,
    4056                 :          0 :                         shadow_thread_count, addr);
    4057                 :          0 :   hbb->append_insn (basic);
    4058                 :            : 
    4059                 :          0 :   hsa_op_reg *tmp2 = new hsa_op_reg (threads->m_type);
    4060                 :          0 :   r = new hsa_op_reg (BRIG_TYPE_B1);
    4061                 :          0 :   hsa_op_immed *imm = new hsa_op_immed (0, shadow_thread_count->m_type);
    4062                 :          0 :   hbb->append_insn (new hsa_insn_cmp (BRIG_COMPARE_EQ, r->m_type, r, tmp, imm));
    4063                 :          0 :   hbb->append_insn (new hsa_insn_basic (4, BRIG_OPCODE_CMOV, btype, tmp2, r,
    4064                 :          0 :                                         shadow_thread_count, tmp));
    4065                 :            : 
    4066                 :          0 :   hsa_op_base *dest = tmp2->get_in_type (BRIG_TYPE_U16, hbb);
    4067                 :            : 
    4068                 :          0 :   return as_a <hsa_op_reg *> (dest);
    4069                 :            : }
    4070                 :            : 
    4071                 :            : /* Build OPCODE query for all three hsa dimensions, multiply them and store the
    4072                 :            :    result into DEST.  */
    4073                 :            : 
    4074                 :            : static void
    4075                 :          0 : multiply_grid_dim_characteristics (hsa_op_reg *dest, int opcode, hsa_bb *hbb)
    4076                 :            : {
    4077                 :          0 :   hsa_op_reg *dimx = new hsa_op_reg (BRIG_TYPE_U32);
    4078                 :          0 :   query_hsa_grid_dim (dimx, opcode,
    4079                 :          0 :                       new hsa_op_immed (0, (BrigKind16_t) BRIG_TYPE_U32), hbb);
    4080                 :          0 :   hsa_op_reg *dimy = new hsa_op_reg (BRIG_TYPE_U32);
    4081                 :          0 :   query_hsa_grid_dim (dimy, opcode,
    4082                 :          0 :                       new hsa_op_immed (1, (BrigKind16_t) BRIG_TYPE_U32), hbb);
    4083                 :          0 :   hsa_op_reg *dimz = new hsa_op_reg (BRIG_TYPE_U32);
    4084                 :          0 :   query_hsa_grid_dim (dimz, opcode,
    4085                 :          0 :                       new hsa_op_immed (2, (BrigKind16_t) BRIG_TYPE_U32), hbb);
    4086                 :          0 :   hsa_op_reg *tmp = new hsa_op_reg (dest->m_type);
    4087                 :          0 :   gen_hsa_binary_operation (BRIG_OPCODE_MUL, tmp,
    4088                 :          0 :                             dimx->get_in_type (dest->m_type, hbb),
    4089                 :          0 :                             dimy->get_in_type (dest->m_type, hbb), hbb);
    4090                 :          0 :   gen_hsa_binary_operation (BRIG_OPCODE_MUL, dest, tmp,
    4091                 :          0 :                             dimz->get_in_type (dest->m_type, hbb), hbb);
    4092                 :          0 : }
    4093                 :            : 
    4094                 :            : /* Emit instructions that assign number of threads to lhs of gimple STMT.
    4095                 :            :    Instructions are appended to basic block HBB.  */
    4096                 :            : 
    4097                 :            : static void
    4098                 :          0 : gen_get_num_threads (gimple *stmt, hsa_bb *hbb)
    4099                 :            : {
    4100                 :          0 :   if (gimple_call_lhs (stmt) == NULL_TREE)
    4101                 :            :     return;
    4102                 :            : 
    4103                 :          0 :   hbb->append_insn (new hsa_insn_comment ("omp_get_num_threads"));
    4104                 :          0 :   tree lhs = gimple_call_lhs (stmt);
    4105                 :          0 :   hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
    4106                 :          0 :   multiply_grid_dim_characteristics (dest, BRIG_OPCODE_CURRENTWORKGROUPSIZE,
    4107                 :            :                                      hbb);
    4108                 :            : }
    4109                 :            : 
    4110                 :            : /* Emit instructions that assign number of teams to lhs of gimple STMT.
    4111                 :            :    Instructions are appended to basic block HBB.  */
    4112                 :            : 
    4113                 :            : static void
    4114                 :          0 : gen_get_num_teams (gimple *stmt, hsa_bb *hbb)
    4115                 :            : {
    4116                 :          0 :   if (gimple_call_lhs (stmt) == NULL_TREE)
    4117                 :            :     return;
    4118                 :            : 
    4119                 :          0 :   hbb->append_insn (new hsa_insn_comment ("omp_get_num_teams"));
    4120                 :          0 :   tree lhs = gimple_call_lhs (stmt);
    4121                 :          0 :   hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
    4122                 :          0 :   multiply_grid_dim_characteristics (dest, BRIG_OPCODE_GRIDGROUPS, hbb);
    4123                 :            : }
    4124                 :            : 
    4125                 :            : /* Emit instructions that assign a team number to lhs of gimple STMT.
    4126                 :            :    Instructions are appended to basic block HBB.  */
    4127                 :            : 
    4128                 :            : static void
    4129                 :          0 : gen_get_team_num (gimple *stmt, hsa_bb *hbb)
    4130                 :            : {
    4131                 :          0 :   if (gimple_call_lhs (stmt) == NULL_TREE)
    4132                 :            :     return;
    4133                 :            : 
    4134                 :          0 :   hbb->append_insn (new hsa_insn_comment ("omp_get_team_num"));
    4135                 :          0 :   tree lhs = gimple_call_lhs (stmt);
    4136                 :          0 :   hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
    4137                 :            : 
    4138                 :          0 :   hsa_op_reg *gnum_x = new hsa_op_reg (BRIG_TYPE_U32);
    4139                 :          0 :   query_hsa_grid_dim (gnum_x, BRIG_OPCODE_GRIDGROUPS,
    4140                 :          0 :                       new hsa_op_immed (0, (BrigKind16_t) BRIG_TYPE_U32), hbb);
    4141                 :          0 :   hsa_op_reg *gnum_y = new hsa_op_reg (BRIG_TYPE_U32);
    4142                 :          0 :   query_hsa_grid_dim (gnum_y, BRIG_OPCODE_GRIDGROUPS,
    4143                 :          0 :                       new hsa_op_immed (1, (BrigKind16_t) BRIG_TYPE_U32), hbb);
    4144                 :            : 
    4145                 :          0 :   hsa_op_reg *gno_z = new hsa_op_reg (BRIG_TYPE_U32);
    4146                 :          0 :   query_hsa_grid_dim (gno_z, BRIG_OPCODE_WORKGROUPID,
    4147                 :          0 :                       new hsa_op_immed (2, (BrigKind16_t) BRIG_TYPE_U32), hbb);
    4148                 :            : 
    4149                 :          0 :   hsa_op_reg *tmp1 = new hsa_op_reg (dest->m_type);
    4150                 :          0 :   gen_hsa_binary_operation (BRIG_OPCODE_MUL, tmp1,
    4151                 :          0 :                             gnum_x->get_in_type (dest->m_type, hbb),
    4152                 :          0 :                             gnum_y->get_in_type (dest->m_type, hbb), hbb);
    4153                 :          0 :   hsa_op_reg *tmp2 = new hsa_op_reg (dest->m_type);
    4154                 :          0 :   gen_hsa_binary_operation (BRIG_OPCODE_MUL, tmp2, tmp1,
    4155                 :          0 :                             gno_z->get_in_type (dest->m_type, hbb), hbb);
    4156                 :            : 
    4157                 :          0 :   hsa_op_reg *gno_y = new hsa_op_reg (BRIG_TYPE_U32);
    4158                 :          0 :   query_hsa_grid_dim (gno_y, BRIG_OPCODE_WORKGROUPID,
    4159                 :          0 :                       new hsa_op_immed (1, (BrigKind16_t) BRIG_TYPE_U32), hbb);
    4160                 :          0 :   hsa_op_reg *tmp3 = new hsa_op_reg (dest->m_type);
    4161                 :          0 :   gen_hsa_binary_operation (BRIG_OPCODE_MUL, tmp3,
    4162                 :          0 :                             gnum_x->get_in_type (dest->m_type, hbb),
    4163                 :          0 :                             gno_y->get_in_type (dest->m_type, hbb), hbb);
    4164                 :          0 :   hsa_op_reg *tmp4 = new hsa_op_reg (dest->m_type);
    4165                 :          0 :   gen_hsa_binary_operation (BRIG_OPCODE_ADD, tmp4, tmp3, tmp2, hbb);
    4166                 :          0 :   hsa_op_reg *gno_x = new hsa_op_reg (BRIG_TYPE_U32);
    4167                 :          0 :   query_hsa_grid_dim (gno_x, BRIG_OPCODE_WORKGROUPID,
    4168                 :          0 :                       new hsa_op_immed (0, (BrigKind16_t) BRIG_TYPE_U32), hbb);
    4169                 :          0 :   gen_hsa_binary_operation (BRIG_OPCODE_ADD, dest, tmp4,
    4170                 :          0 :                             gno_x->get_in_type (dest->m_type, hbb), hbb);
    4171                 :            : }
    4172                 :            : 
    4173                 :            : /* Emit instructions that get levels-var ICV to lhs of gimple STMT.
    4174                 :            :    Instructions are appended to basic block HBB.  */
    4175                 :            : 
    4176                 :            : static void
    4177                 :          0 : gen_get_level (gimple *stmt, hsa_bb *hbb)
    4178                 :            : {
    4179                 :          0 :   if (gimple_call_lhs (stmt) == NULL_TREE)
    4180                 :            :     return;
    4181                 :            : 
    4182                 :          0 :   hbb->append_insn (new hsa_insn_comment ("omp_get_level"));
    4183                 :            : 
    4184                 :          0 :   tree lhs = gimple_call_lhs (stmt);
    4185                 :          0 :   hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
    4186                 :            : 
    4187                 :          0 :   hsa_op_reg *shadow_reg_ptr = hsa_cfun->get_shadow_reg ();
    4188                 :          0 :   if (shadow_reg_ptr == NULL)
    4189                 :            :     {
    4190                 :          0 :       HSA_SORRY_AT (gimple_location (stmt),
    4191                 :            :                     "support for HSA does not implement %<omp_get_level%> "
    4192                 :            :                     "called from a function not being inlined within a kernel");
    4193                 :          0 :       return;
    4194                 :            :     }
    4195                 :            : 
    4196                 :          0 :   hsa_op_address *addr
    4197                 :            :     = new hsa_op_address (shadow_reg_ptr,
    4198                 :          0 :                           get_hsa_kernel_dispatch_offset ("omp_level"));
    4199                 :            : 
    4200                 :          0 :   hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, BRIG_TYPE_U64,
    4201                 :          0 :                                         (hsa_op_base *) NULL, addr);
    4202                 :          0 :   hbb->append_insn (mem);
    4203                 :          0 :   mem->set_output_in_type (dest, 0, hbb);
    4204                 :            : }
    4205                 :            : 
    4206                 :            : /* Emit instruction that implement omp_get_max_threads of gimple STMT.  */
    4207                 :            : 
    4208                 :            : static void
    4209                 :          0 : gen_get_max_threads (gimple *stmt, hsa_bb *hbb)
    4210                 :            : {
    4211                 :          0 :   tree lhs = gimple_call_lhs (stmt);
    4212                 :          0 :   if (!lhs)
    4213                 :            :     return;
    4214                 :            : 
    4215                 :          0 :   hbb->append_insn (new hsa_insn_comment ("omp_get_max_threads"));
    4216                 :            : 
    4217                 :          0 :   hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
    4218                 :          0 :   hsa_op_with_type *num_theads_reg = gen_num_threads_for_dispatch (hbb)
    4219                 :          0 :     ->get_in_type (dest->m_type, hbb);
    4220                 :          0 :   hsa_build_append_simple_mov (dest, num_theads_reg, hbb);
    4221                 :            : }
    4222                 :            : 
    4223                 :            : /* Emit instructions that implement alloca builtin gimple STMT.
    4224                 :            :    Instructions are appended to basic block HBB.  */
    4225                 :            : 
    4226                 :            : static void
    4227                 :          0 : gen_hsa_alloca (gcall *call, hsa_bb *hbb)
    4228                 :            : {
    4229                 :          0 :   tree lhs = gimple_call_lhs (call);
    4230                 :          0 :   if (lhs == NULL_TREE)
    4231                 :            :     return;
    4232                 :            : 
    4233                 :          0 :   tree fndecl = gimple_call_fndecl (call);
    4234                 :          0 :   built_in_function fn = DECL_FUNCTION_CODE (fndecl);
    4235                 :            : 
    4236                 :          0 :   gcc_checking_assert (ALLOCA_FUNCTION_CODE_P (fn));
    4237                 :            : 
    4238                 :          0 :   unsigned bit_alignment = 0;
    4239                 :            : 
    4240                 :          0 :   if (fn != BUILT_IN_ALLOCA)
    4241                 :            :     {
    4242                 :          0 :       tree alignment_tree = gimple_call_arg (call, 1);
    4243                 :          0 :       if (TREE_CODE (alignment_tree) != INTEGER_CST)
    4244                 :            :         {
    4245                 :          0 :           HSA_SORRY_ATV (gimple_location (call),
    4246                 :            :                          "support for HSA does not implement "
    4247                 :            :                          "%qD with a non-constant alignment %E",
    4248                 :            :                          fndecl, alignment_tree);
    4249                 :            :         }
    4250                 :            : 
    4251                 :          0 :       bit_alignment = tree_to_uhwi (alignment_tree);
    4252                 :            :     }
    4253                 :            : 
    4254                 :          0 :   tree rhs1 = gimple_call_arg (call, 0);
    4255                 :          0 :   hsa_op_with_type *size = hsa_reg_or_immed_for_gimple_op (rhs1, hbb)
    4256                 :          0 :     ->get_in_type (BRIG_TYPE_U32, hbb);
    4257                 :          0 :   hsa_op_with_type *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
    4258                 :            : 
    4259                 :          0 :   hsa_op_reg *tmp
    4260                 :          0 :     = new hsa_op_reg (hsa_get_segment_addr_type (BRIG_SEGMENT_PRIVATE));
    4261                 :          0 :   hsa_insn_alloca *a = new hsa_insn_alloca (tmp, size, bit_alignment);
    4262                 :          0 :   hbb->append_insn (a);
    4263                 :            : 
    4264                 :          0 :   hsa_insn_seg *seg
    4265                 :            :     = new hsa_insn_seg (BRIG_OPCODE_STOF,
    4266                 :          0 :                         hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT),
    4267                 :          0 :                         tmp->m_type, BRIG_SEGMENT_PRIVATE, dest, tmp);
    4268                 :          0 :   hbb->append_insn (seg);
    4269                 :            : }
    4270                 :            : 
    4271                 :            : /* Emit instructions that implement clrsb builtin STMT:
    4272                 :            :    Returns the number of leading redundant sign bits in x, i.e. the number
    4273                 :            :    of bits following the most significant bit that are identical to it.
    4274                 :            :    There are no special cases for 0 or other values.
    4275                 :            :    Instructions are appended to basic block HBB.  */
    4276                 :            : 
    4277                 :            : static void
    4278                 :          0 : gen_hsa_clrsb (gcall *call, hsa_bb *hbb)
    4279                 :            : {
    4280                 :          0 :   tree lhs = gimple_call_lhs (call);
    4281                 :          0 :   if (lhs == NULL_TREE)
    4282                 :            :     return;
    4283                 :            : 
    4284                 :          0 :   hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
    4285                 :          0 :   tree rhs1 = gimple_call_arg (call, 0);
    4286                 :          0 :   hsa_op_with_type *arg = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
    4287                 :          0 :   arg->extend_int_to_32bit (hbb);
    4288                 :          0 :   BrigType16_t bittype = hsa_bittype_for_type (arg->m_type);
    4289                 :          0 :   unsigned bitsize = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (rhs1)));
    4290                 :            : 
    4291                 :            :   /* FIRSTBIT instruction is defined just for 32 and 64-bits wide integers.  */
    4292                 :          0 :   gcc_checking_assert (bitsize == 32 || bitsize == 64);
    4293                 :            : 
    4294                 :            :   /* Set true to MOST_SIG if the most significant bit is set to one.  */
    4295                 :          0 :   hsa_op_immed *c = new hsa_op_immed (1ul << (bitsize - 1),
    4296                 :          0 :                                       hsa_uint_for_bitsize (bitsize));
    4297                 :            : 
    4298                 :          0 :   hsa_op_reg *and_reg = new hsa_op_reg (bittype);
    4299                 :          0 :   gen_hsa_binary_operation (BRIG_OPCODE_AND, and_reg, arg, c, hbb);
    4300                 :            : 
    4301                 :          0 :   hsa_op_reg *most_sign = new hsa_op_reg (BRIG_TYPE_B1);
    4302                 :          0 :   hsa_insn_cmp *cmp
    4303                 :          0 :     = new hsa_insn_cmp (BRIG_COMPARE_EQ, most_sign->m_type, most_sign,
    4304                 :          0 :                         and_reg, c);
    4305                 :          0 :   hbb->append_insn (cmp);
    4306                 :            : 
    4307                 :            :   /* If the most significant bit is one, negate the input.  Otherwise
    4308                 :            :      shift the input value to left by one bit.  */
    4309                 :          0 :   hsa_op_reg *arg_neg = new hsa_op_reg (arg->m_type);
    4310                 :          0 :   gen_hsa_unary_operation (BRIG_OPCODE_NEG, arg_neg, arg, hbb);
    4311                 :            : 
    4312                 :          0 :   hsa_op_reg *shifted_arg = new hsa_op_reg (arg->m_type);
    4313                 :          0 :   gen_hsa_binary_operation (BRIG_OPCODE_SHL, shifted_arg, arg,
    4314                 :          0 :                             new hsa_op_immed (1, BRIG_TYPE_U64), hbb);
    4315                 :            : 
    4316                 :            :   /* Assign the value that can be used for FIRSTBIT instruction according
    4317                 :            :      to the most significant bit.  */
    4318                 :          0 :   hsa_op_reg *tmp = new hsa_op_reg (bittype);
    4319                 :          0 :   hsa_insn_basic *cmov
    4320                 :            :     = new hsa_insn_basic (4, BRIG_OPCODE_CMOV, bittype, tmp, most_sign,
    4321                 :          0 :                           arg_neg, shifted_arg);
    4322                 :          0 :   hbb->append_insn (cmov);
    4323                 :            : 
    4324                 :          0 :   hsa_op_reg *leading_bits = new hsa_op_reg (BRIG_TYPE_S32);
    4325                 :          0 :   gen_hsa_unary_operation (BRIG_OPCODE_FIRSTBIT, leading_bits,
    4326                 :          0 :                            tmp->get_in_type (hsa_uint_for_bitsize (bitsize),
    4327                 :            :                                              hbb), hbb);
    4328                 :            : 
    4329                 :            :   /* Set flag if the input value is equal to zero.  */
    4330                 :          0 :   hsa_op_reg *is_zero = new hsa_op_reg (BRIG_TYPE_B1);
    4331                 :          0 :   cmp = new hsa_insn_cmp (BRIG_COMPARE_EQ, is_zero->m_type, is_zero, arg,
    4332                 :          0 :                           new hsa_op_immed (0, arg->m_type));
    4333                 :          0 :   hbb->append_insn (cmp);
    4334                 :            : 
    4335                 :            :   /* Return the number of leading bits,
    4336                 :            :      or (bitsize - 1) if the input value is zero.  */
    4337                 :          0 :   cmov = new hsa_insn_basic (4, BRIG_OPCODE_CMOV, BRIG_TYPE_B32, NULL, is_zero,
    4338                 :          0 :                              new hsa_op_immed (bitsize - 1, BRIG_TYPE_U32),
    4339                 :          0 :                              leading_bits->get_in_type (BRIG_TYPE_B32, hbb));
    4340                 :          0 :   hbb->append_insn (cmov);
    4341                 :          0 :   cmov->set_output_in_type (dest, 0, hbb);
    4342                 :            : }
    4343                 :            : 
    4344                 :            : /* Emit instructions that implement ffs builtin STMT:
    4345                 :            :    Returns one plus the index of the least significant 1-bit of x,
    4346                 :            :    or if x is zero, returns zero.
    4347                 :            :    Instructions are appended to basic block HBB.  */
    4348                 :            : 
    4349                 :            : static void
    4350                 :          0 : gen_hsa_ffs (gcall *call, hsa_bb *hbb)
    4351                 :            : {
    4352                 :          0 :   tree lhs = gimple_call_lhs (call);
    4353                 :          0 :   if (lhs == NULL_TREE)
    4354                 :            :     return;
    4355                 :            : 
    4356                 :          0 :   hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
    4357                 :            : 
    4358                 :          0 :   tree rhs1 = gimple_call_arg (call, 0);
    4359                 :          0 :   hsa_op_with_type *arg = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
    4360                 :          0 :   arg = arg->extend_int_to_32bit (hbb);
    4361                 :            : 
    4362                 :          0 :   hsa_op_reg *tmp = new hsa_op_reg (BRIG_TYPE_U32);
    4363                 :          0 :   hsa_insn_srctype *insn = new hsa_insn_srctype (2, BRIG_OPCODE_LASTBIT,
    4364                 :          0 :                                                  tmp->m_type, arg->m_type,
    4365                 :          0 :                                                  tmp, arg);
    4366                 :          0 :   hbb->append_insn (insn);
    4367                 :            : 
    4368                 :          0 :   hsa_insn_basic *addition
    4369                 :          0 :     = new hsa_insn_basic (3, BRIG_OPCODE_ADD, tmp->m_type, NULL, tmp,
    4370                 :          0 :                           new hsa_op_immed (1, tmp->m_type));
    4371                 :          0 :   hbb->append_insn (addition);
    4372                 :          0 :   addition->set_output_in_type (dest, 0, hbb);
    4373                 :            : }
    4374                 :            : 
    4375                 :            : static void
    4376                 :          0 : gen_hsa_popcount_to_dest (hsa_op_reg *dest, hsa_op_with_type *arg, hsa_bb *hbb)
    4377                 :            : {
    4378                 :          0 :   gcc_checking_assert (hsa_type_integer_p (arg->m_type));
    4379                 :            : 
    4380                 :          0 :   if (hsa_type_bit_size (arg->m_type) < 32)
    4381                 :          0 :     arg = arg->get_in_type (BRIG_TYPE_B32, hbb);
    4382                 :            : 
    4383                 :          0 :   BrigType16_t srctype = hsa_bittype_for_type (arg->m_type);
    4384                 :          0 :   if (!hsa_btype_p (arg->m_type))
    4385                 :          0 :     arg = arg->get_in_type (srctype, hbb);
    4386                 :            : 
    4387                 :          0 :   hsa_insn_srctype *popcount
    4388                 :            :     = new hsa_insn_srctype (2, BRIG_OPCODE_POPCOUNT, BRIG_TYPE_U32,
    4389                 :          0 :                             srctype, NULL, arg);
    4390                 :          0 :   hbb->append_insn (popcount);
    4391                 :          0 :   popcount->set_output_in_type (dest, 0, hbb);
    4392                 :          0 : }
    4393                 :            : 
    4394                 :            : /* Emit instructions that implement parity builtin STMT:
    4395                 :            :    Returns the parity of x, i.e. the number of 1-bits in x modulo 2.
    4396                 :            :    Instructions are appended to basic block HBB.  */
    4397                 :            : 
    4398                 :            : static void
    4399                 :          0 : gen_hsa_parity (gcall *call, hsa_bb *hbb)
    4400                 :            : {
    4401                 :          0 :   tree lhs = gimple_call_lhs (call);
    4402                 :          0 :   if (lhs == NULL_TREE)
    4403                 :            :     return;
    4404                 :            : 
    4405                 :          0 :   hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
    4406                 :          0 :   tree rhs1 = gimple_call_arg (call, 0);
    4407                 :          0 :   hsa_op_with_type *arg = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
    4408                 :            : 
    4409                 :          0 :   hsa_op_reg *popcount = new hsa_op_reg (BRIG_TYPE_U32);
    4410                 :          0 :   gen_hsa_popcount_to_dest (popcount, arg, hbb);
    4411                 :            : 
    4412                 :          0 :   hsa_insn_basic *insn
    4413                 :          0 :     = new hsa_insn_basic (3, BRIG_OPCODE_REM, popcount->m_type, NULL, popcount,
    4414                 :          0 :                           new hsa_op_immed (2, popcount->m_type));
    4415                 :          0 :   hbb->append_insn (insn);
    4416                 :          0 :   insn->set_output_in_type (dest, 0, hbb);
    4417                 :            : }
    4418                 :            : 
    4419                 :            : /* Emit instructions that implement popcount builtin STMT.
    4420                 :            :    Instructions are appended to basic block HBB.  */
    4421                 :            : 
    4422                 :            : static void
    4423                 :          0 : gen_hsa_popcount (gcall *call, hsa_bb *hbb)
    4424                 :            : {
    4425                 :          0 :   tree lhs = gimple_call_lhs (call);
    4426                 :          0 :   if (lhs == NULL_TREE)
    4427                 :            :     return;
    4428                 :            : 
    4429                 :          0 :   hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
    4430                 :          0 :   tree rhs1 = gimple_call_arg (call, 0);
    4431                 :          0 :   hsa_op_with_type *arg = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
    4432                 :            : 
    4433                 :          0 :   gen_hsa_popcount_to_dest (dest, arg, hbb);
    4434                 :            : }
    4435                 :            : 
    4436                 :            : /* Emit instructions that implement DIVMOD builtin STMT.
    4437                 :            :    Instructions are appended to basic block HBB.  */
    4438                 :            : 
    4439                 :            : static void
    4440                 :          0 : gen_hsa_divmod (gcall *call, hsa_bb *hbb)
    4441                 :            : {
    4442                 :          0 :   tree lhs = gimple_call_lhs (call);
    4443                 :          0 :   if (lhs == NULL_TREE)
    4444                 :            :     return;
    4445                 :            : 
    4446                 :          0 :   tree rhs0 = gimple_call_arg (call, 0);
    4447                 :          0 :   tree rhs1 = gimple_call_arg (call, 1);
    4448                 :            : 
    4449                 :          0 :   hsa_op_with_type *arg0 = hsa_reg_or_immed_for_gimple_op (rhs0, hbb);
    4450                 :          0 :   arg0 = arg0->extend_int_to_32bit (hbb);
    4451                 :          0 :   hsa_op_with_type *arg1 = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
    4452                 :          0 :   arg1 = arg1->extend_int_to_32bit (hbb);
    4453                 :            : 
    4454                 :          0 :   hsa_op_reg *dest0 = new hsa_op_reg (arg0->m_type);
    4455                 :          0 :   hsa_op_reg *dest1 = new hsa_op_reg (arg1->m_type);
    4456                 :            : 
    4457                 :          0 :   hsa_insn_basic *insn = new hsa_insn_basic (3, BRIG_OPCODE_DIV, dest0->m_type,
    4458                 :          0 :                                              dest0, arg0, arg1);
    4459                 :          0 :   hbb->append_insn (insn);
    4460                 :          0 :   insn = new hsa_insn_basic (3, BRIG_OPCODE_REM, dest1->m_type, dest1, arg0,
    4461                 :          0 :                              arg1);
    4462                 :          0 :   hbb->append_insn (insn);
    4463                 :            : 
    4464                 :          0 :   hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
    4465                 :          0 :   BrigType16_t dst_type = hsa_extend_inttype_to_32bit (dest->m_type);
    4466                 :          0 :   BrigType16_t src_type = hsa_bittype_for_type (dest0->m_type);
    4467                 :            : 
    4468                 :          0 :   insn = new hsa_insn_packed (3, BRIG_OPCODE_COMBINE, dst_type,
    4469                 :          0 :                               src_type, NULL, dest0, dest1);
    4470                 :          0 :   hbb->append_insn (insn);
    4471                 :          0 :   insn->set_output_in_type (dest, 0, hbb);
    4472                 :            : }
    4473                 :            : 
    4474                 :            : /* Emit instructions that implement FMA, FMS, FNMA or FNMS call STMT.
    4475                 :            :    Instructions are appended to basic block HBB.  NEGATE1 is true for
    4476                 :            :    FNMA and FNMS.  NEGATE3 is true for FMS and FNMS.  */
    4477                 :            : 
    4478                 :            : static void
    4479                 :          0 : gen_hsa_fma (gcall *call, hsa_bb *hbb, bool negate1, bool negate3)
    4480                 :            : {
    4481                 :          0 :   tree lhs = gimple_call_lhs (call);
    4482                 :          0 :   if (lhs == NULL_TREE)
    4483                 :            :     return;
    4484                 :            : 
    4485                 :          0 :   tree rhs1 = gimple_call_arg (call, 0);
    4486                 :          0 :   tree rhs2 = gimple_call_arg (call, 1);
    4487                 :          0 :   tree rhs3 = gimple_call_arg (call, 2);
    4488                 :            : 
    4489                 :          0 :   hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
    4490                 :          0 :   hsa_op_with_type *op1 = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
    4491                 :          0 :   hsa_op_with_type *op2 = hsa_reg_or_immed_for_gimple_op (rhs2, hbb);
    4492                 :          0 :   hsa_op_with_type *op3 = hsa_reg_or_immed_for_gimple_op (rhs3, hbb);
    4493                 :            : 
    4494                 :          0 :   if (negate1)
    4495                 :            :     {
    4496                 :          0 :       hsa_op_reg *tmp = new hsa_op_reg (dest->m_type);
    4497                 :          0 :       gen_hsa_unary_operation (BRIG_OPCODE_NEG, tmp, op1, hbb);
    4498                 :          0 :       op1 = tmp;
    4499                 :            :     }
    4500                 :            : 
    4501                 :            :   /* There is a native HSA instruction for scalar FMAs but not for vector
    4502                 :            :      ones.  */
    4503                 :          0 :   if (TREE_CODE (TREE_TYPE (lhs)) == VECTOR_TYPE)
    4504                 :            :     {
    4505                 :          0 :       hsa_op_reg *tmp = new hsa_op_reg (dest->m_type);
    4506                 :          0 :       gen_hsa_binary_operation (BRIG_OPCODE_MUL, tmp, op1, op2, hbb);
    4507                 :          0 :       gen_hsa_binary_operation (negate3 ? BRIG_OPCODE_SUB : BRIG_OPCODE_ADD,
    4508                 :            :                                 dest, tmp, op3, hbb);
    4509                 :            :     }
    4510                 :            :   else
    4511                 :            :     {
    4512                 :          0 :       if (negate3)
    4513                 :            :         {
    4514                 :          0 :           hsa_op_reg *tmp = new hsa_op_reg (dest->m_type);
    4515                 :          0 :           gen_hsa_unary_operation (BRIG_OPCODE_NEG, tmp, op3, hbb);
    4516                 :          0 :           op3 = tmp;
    4517                 :            :         }
    4518                 :          0 :       hsa_insn_basic *insn = new hsa_insn_basic (4, BRIG_OPCODE_MAD,
    4519                 :          0 :                                                  dest->m_type, dest,
    4520                 :          0 :                                                  op1, op2, op3);
    4521                 :          0 :       hbb->append_insn (insn);
    4522                 :            :     }
    4523                 :            : }
    4524                 :            : 
    4525                 :            : /* Set VALUE to a shadow kernel debug argument and append a new instruction
    4526                 :            :    to HBB basic block.  */
    4527                 :            : 
    4528                 :            : static void
    4529                 :          0 : set_debug_value (hsa_bb *hbb, hsa_op_with_type *value)
    4530                 :            : {
    4531                 :          0 :   hsa_op_reg *shadow_reg_ptr = hsa_cfun->get_shadow_reg ();
    4532                 :          0 :   if (shadow_reg_ptr == NULL)
    4533                 :            :     return;
    4534                 :            : 
    4535                 :          0 :   hsa_op_address *addr
    4536                 :            :     = new hsa_op_address (shadow_reg_ptr,
    4537                 :          0 :                           get_hsa_kernel_dispatch_offset ("debug"));
    4538                 :          0 :   hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, BRIG_TYPE_U64, value,
    4539                 :          0 :                                         addr);
    4540                 :          0 :   hbb->append_insn (mem);
    4541                 :            : }
    4542                 :            : 
    4543                 :            : void
    4544                 :          0 : omp_simple_builtin::generate (gimple *stmt, hsa_bb *hbb)
    4545                 :            : {
    4546                 :          0 :   if (m_sorry)
    4547                 :            :     {
    4548                 :          0 :       if (m_warning_message)
    4549                 :          0 :         HSA_SORRY_AT (gimple_location (stmt), m_warning_message);
    4550                 :            :       else
    4551                 :          0 :         HSA_SORRY_ATV (gimple_location (stmt),
    4552                 :            :                        "support for HSA does not implement calls to %qs",
    4553                 :            :                        m_name);
    4554                 :            :     }
    4555                 :          0 :   else if (m_warning_message != NULL)
    4556                 :          0 :     warning_at (gimple_location (stmt), OPT_Whsa, m_warning_message);
    4557                 :            : 
    4558                 :          0 :   if (m_return_value != NULL)
    4559                 :            :     {
    4560                 :          0 :       tree lhs = gimple_call_lhs (stmt);
    4561                 :          0 :       if (!lhs)
    4562                 :            :         return;
    4563                 :            : 
    4564                 :          0 :       hbb->append_insn (new hsa_insn_comment (m_name));
    4565                 :            : 
    4566                 :          0 :       hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
    4567                 :          0 :       hsa_op_with_type *op = m_return_value->get_in_type (dest->m_type, hbb);
    4568                 :          0 :       hsa_build_append_simple_mov (dest, op, hbb);
    4569                 :            :     }
    4570                 :            : }
    4571                 :            : 
    4572                 :            : /* If STMT is a call of a known library function, generate code to perform
    4573                 :            :    it and return true.  */
    4574                 :            : 
    4575                 :            : static bool
    4576                 :          0 : gen_hsa_insns_for_known_library_call (gimple *stmt, hsa_bb *hbb)
    4577                 :            : {
    4578                 :          0 :   bool handled = false;
    4579                 :          0 :   const char *name = hsa_get_declaration_name (gimple_call_fndecl (stmt));
    4580                 :            : 
    4581                 :          0 :   char *copy = NULL;
    4582                 :          0 :   size_t len = strlen (name);
    4583                 :          0 :   if (len > 0 && name[len - 1] == '_')
    4584                 :            :     {
    4585                 :          0 :       copy = XNEWVEC (char, len + 1);
    4586                 :          0 :       strcpy (copy, name);
    4587                 :          0 :       copy[len - 1] = '\0';
    4588                 :          0 :       name = copy;
    4589                 :            :     }
    4590                 :            : 
    4591                 :            :   /* Handle omp_* routines.  */
    4592                 :          0 :   if (strstr (name, "omp_") == name)
    4593                 :            :     {
    4594                 :          0 :       hsa_init_simple_builtins ();
    4595                 :          0 :       omp_simple_builtin *builtin = omp_simple_builtins->get (name);
    4596                 :          0 :       if (builtin)
    4597                 :            :         {
    4598                 :          0 :           builtin->generate (stmt, hbb);
    4599                 :          0 :           return true;
    4600                 :            :         }
    4601                 :            : 
    4602                 :          0 :       handled = true;
    4603                 :          0 :       if (strcmp (name, "omp_set_num_threads") == 0)
    4604                 :          0 :         gen_set_num_threads (gimple_call_arg (stmt, 0), hbb);
    4605                 :          0 :       else if (strcmp (name, "omp_get_thread_num") == 0)
    4606                 :            :         {
    4607                 :          0 :           hbb->append_insn (new hsa_insn_comment (name));
    4608                 :          0 :           query_hsa_grid_nodim (stmt, BRIG_OPCODE_WORKITEMFLATABSID, hbb);
    4609                 :            :         }
    4610                 :          0 :       else if (strcmp (name, "omp_get_num_threads") == 0)
    4611                 :            :         {
    4612                 :          0 :           hbb->append_insn (new hsa_insn_comment (name));
    4613                 :          0 :           gen_get_num_threads (stmt, hbb);
    4614                 :            :         }
    4615                 :          0 :       else if (strcmp (name, "omp_get_num_teams") == 0)
    4616                 :          0 :         gen_get_num_teams (stmt, hbb);
    4617                 :          0 :       else if (strcmp (name, "omp_get_team_num") == 0)
    4618                 :          0 :         gen_get_team_num (stmt, hbb);
    4619                 :          0 :       else if (strcmp (name, "omp_get_level") == 0)
    4620                 :          0 :         gen_get_level (stmt, hbb);
    4621                 :          0 :       else if (strcmp (name, "omp_get_active_level") == 0)
    4622                 :          0 :         gen_get_level (stmt, hbb);
    4623                 :          0 :       else if (strcmp (name, "omp_in_parallel") == 0)
    4624                 :          0 :         gen_get_level (stmt, hbb);
    4625                 :          0 :       else if (strcmp (name, "omp_get_max_threads") == 0)
    4626                 :          0 :         gen_get_max_threads (stmt, hbb);
    4627                 :            :       else
    4628                 :            :         handled = false;
    4629                 :            : 
    4630                 :          0 :       if (handled)
    4631                 :            :         {
    4632                 :          0 :           if (copy)
    4633                 :          0 :             free (copy);
    4634                 :          0 :           return true;
    4635                 :            :         }
    4636                 :            :     }
    4637                 :            : 
    4638                 :          0 :   if (strcmp (name, "__hsa_set_debug_value") == 0)
    4639                 :            :     {
    4640                 :          0 :       handled = true;
    4641                 :          0 :       if (hsa_cfun->has_shadow_reg_p ())
    4642                 :            :         {
    4643                 :          0 :           tree rhs1 = gimple_call_arg (stmt, 0);
    4644                 :          0 :           hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
    4645                 :            : 
    4646                 :          0 :           src = src->get_in_type (BRIG_TYPE_U64, hbb);
    4647                 :          0 :           set_debug_value (hbb, src);
    4648                 :            :         }
    4649                 :            :     }
    4650                 :            : 
    4651                 :          0 :   if (copy)
    4652                 :          0 :     free (copy);
    4653                 :            :   return handled;
    4654                 :            : }
    4655                 :            : 
    4656                 :            : /* Helper functions to create a single unary HSA operations out of calls to
    4657                 :            :    builtins.  OPCODE is the HSA operation to be generated.  STMT is a gimple
    4658                 :            :    call to a builtin.  HBB is the HSA BB to which the instruction should be
    4659                 :            :    added.  Note that nothing will be created if STMT does not have a LHS.  */
    4660                 :            : 
    4661                 :            : static void
    4662                 :          0 : gen_hsa_unaryop_for_builtin (BrigOpcode opcode, gimple *stmt, hsa_bb *hbb)
    4663                 :            : {
    4664                 :          0 :   tree lhs = gimple_call_lhs (stmt);
    4665                 :          0 :   if (!lhs)
    4666                 :            :     return;
    4667                 :          0 :   hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
    4668                 :          0 :   hsa_op_with_type *op
    4669                 :          0 :     = hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 0), hbb);
    4670                 :          0 :   gen_hsa_unary_operation (opcode, dest, op, hbb);
    4671                 :            : }
    4672                 :            : 
    4673                 :            : /* Helper functions to create a call to standard library if LHS of the
    4674                 :            :    STMT is used.  HBB is the HSA BB to which the instruction should be
    4675                 :            :    added.  */
    4676                 :            : 
    4677                 :            : static void
    4678                 :          0 : gen_hsa_unaryop_builtin_call (gimple *stmt, hsa_bb *hbb)
    4679                 :            : {
    4680                 :          0 :   tree lhs = gimple_call_lhs (stmt);
    4681                 :          0 :   if (!lhs)
    4682                 :            :     return;
    4683                 :            : 
    4684                 :          0 :   if (gimple_call_internal_p (stmt))
    4685                 :          0 :     gen_hsa_insns_for_call_of_internal_fn (stmt, hbb);
    4686                 :            :   else
    4687                 :          0 :     gen_hsa_insns_for_direct_call (stmt, hbb);
    4688                 :            : }
    4689                 :            : 
    4690                 :            : /* Helper functions to create a single unary HSA operations out of calls to
    4691                 :            :    builtins (if unsafe math optimizations are enable). Otherwise, create
    4692                 :            :    a call to standard library function.
    4693                 :            :    OPCODE is the HSA operation to be generated.  STMT is a gimple
    4694                 :            :    call to a builtin.  HBB is the HSA BB to which the instruction should be
    4695                 :            :    added.  Note that nothing will be created if STMT does not have a LHS.  */
    4696                 :            : 
    4697                 :            : static void
    4698                 :          0 : gen_hsa_unaryop_or_call_for_builtin (BrigOpcode opcode, gimple *stmt,
    4699                 :            :                                      hsa_bb *hbb)
    4700                 :            : {
    4701                 :          0 :   if (flag_unsafe_math_optimizations)
    4702                 :          0 :     gen_hsa_unaryop_for_builtin (opcode, stmt, hbb);
    4703                 :            :   else
    4704                 :          0 :     gen_hsa_unaryop_builtin_call (stmt, hbb);
    4705                 :          0 : }
    4706                 :            : 
    4707                 :            : /* Generate HSA address corresponding to a value VAL (as opposed to a memory
    4708                 :            :    reference tree), for example an SSA_NAME or an ADDR_EXPR.  HBB is the HSA BB
    4709                 :            :    to which the instruction should be added.  */
    4710                 :            : 
    4711                 :            : static hsa_op_address *
    4712                 :          0 : get_address_from_value (tree val, hsa_bb *hbb)
    4713                 :            : {
    4714                 :          0 :   switch (TREE_CODE (val))
    4715                 :            :     {
    4716                 :          0 :     case SSA_NAME:
    4717                 :          0 :       {
    4718                 :          0 :         BrigType16_t addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
    4719                 :          0 :         hsa_op_base *reg
    4720                 :          0 :           = hsa_cfun->reg_for_gimple_ssa (val)->get_in_type (addrtype, hbb);
    4721                 :          0 :         return new hsa_op_address (NULL, as_a <hsa_op_reg *> (reg), 0);
    4722                 :            :       }
    4723                 :          0 :     case ADDR_EXPR:
    4724                 :          0 :       return gen_hsa_addr (TREE_OPERAND (val, 0), hbb);
    4725                 :            : 
    4726                 :          0 :     case INTEGER_CST:
    4727                 :          0 :       if (tree_fits_shwi_p (val))
    4728                 :          0 :         return new hsa_op_address (NULL, NULL, tree_to_shwi (val));
    4729                 :            :       /* fall-through */
    4730                 :            : 
    4731                 :          0 :     default:
    4732                 :          0 :       HSA_SORRY_ATV (EXPR_LOCATION (val),
    4733                 :            :                      "support for HSA does not implement memory access to %E",
    4734                 :            :                      val);
    4735                 :          0 :       return new hsa_op_address (NULL, NULL, 0);
    4736                 :            :     }
    4737                 :            : }
    4738                 :            : 
    4739                 :            : /* Expand assignment of a result of a string BUILTIN to DST.
    4740                 :            :    Size of the operation is N bytes, where instructions
    4741                 :            :    will be append to HBB.  */
    4742                 :            : 
    4743                 :            : static void
    4744                 :          0 : expand_lhs_of_string_op (gimple *stmt,
    4745                 :            :                          unsigned HOST_WIDE_INT n, hsa_bb *hbb,
    4746                 :            :                          enum built_in_function builtin)
    4747                 :            : {
    4748                 :            :   /* If LHS is expected, we need to emit a PHI instruction.  */
    4749                 :          0 :   tree lhs = gimple_call_lhs (stmt);
    4750                 :          0 :   if (!lhs)
    4751                 :            :     return;
    4752                 :            : 
    4753                 :          0 :   hsa_op_reg *lhs_reg = hsa_cfun->reg_for_gimple_ssa (lhs);
    4754                 :            : 
    4755                 :          0 :   hsa_op_with_type *dst_reg
    4756                 :          0 :     = hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 0), hbb);
    4757                 :          0 :   hsa_op_with_type *tmp;
    4758                 :            : 
    4759                 :          0 :   switch (builtin)
    4760                 :            :     {
    4761                 :          0 :     case BUILT_IN_MEMPCPY:
    4762                 :          0 :       {
    4763                 :          0 :         tmp = new hsa_op_reg (dst_reg->m_type);
    4764                 :          0 :         hsa_insn_basic *add
    4765                 :          0 :           = new hsa_insn_basic (3, BRIG_OPCODE_ADD, tmp->m_type,
    4766                 :            :                                 tmp, dst_reg,
    4767                 :          0 :                                 new hsa_op_immed (n, dst_reg->m_type));
    4768                 :          0 :         hbb->append_insn (add);
    4769                 :          0 :         break;
    4770                 :            :       }
    4771                 :            :     case BUILT_IN_MEMCPY:
    4772                 :            :     case BUILT_IN_MEMSET:
    4773                 :            :       tmp = dst_reg;
    4774                 :            :       break;
    4775                 :          0 :     default:
    4776                 :          0 :       gcc_unreachable ();
    4777                 :            :     }
    4778                 :            : 
    4779                 :          0 :   hbb->append_insn (new hsa_insn_basic (2, BRIG_OPCODE_MOV, lhs_reg->m_type,
    4780                 :          0 :                                         lhs_reg, tmp));
    4781                 :            : }
    4782                 :            : 
    4783                 :            : #define HSA_MEMORY_BUILTINS_LIMIT     128
    4784                 :            : 
    4785                 :            : /* Expand a string builtin (from a gimple STMT) in a way that
    4786                 :            :    according to MISALIGNED_FLAG we process either direct emission
    4787                 :            :    (a bunch of memory load and store instructions), or we emit a function call
    4788                 :            :    of a library function (for instance 'memcpy'). Actually, a basic block
    4789                 :            :    for direct emission is just prepared, where caller is responsible
    4790                 :            :    for emission of corresponding instructions.
    4791                 :            :    All instruction are appended to HBB.  */
    4792                 :            : 
    4793                 :            : hsa_bb *
    4794                 :          0 : expand_string_operation_builtin (gimple *stmt, hsa_bb *hbb,
    4795                 :            :                                  hsa_op_reg *misaligned_flag)
    4796                 :            : {
    4797                 :          0 :   edge e = split_block (hbb->m_bb, stmt);
    4798                 :          0 :   basic_block condition_bb = e->src;
    4799                 :          0 :   hbb->append_insn (new hsa_insn_cbr (misaligned_flag));
    4800                 :            : 
    4801                 :            :   /* Prepare the control flow.  */
    4802                 :          0 :   edge condition_edge = EDGE_SUCC (condition_bb, 0);
    4803                 :          0 :   basic_block call_bb = split_edge (condition_edge);
    4804                 :            : 
    4805                 :          0 :   basic_block expanded_bb = split_edge (EDGE_SUCC (call_bb, 0));
    4806                 :          0 :   basic_block cont_bb = EDGE_SUCC (expanded_bb, 0)->dest;
    4807                 :          0 :   basic_block merge_bb = split_edge (EDGE_PRED (cont_bb, 0));
    4808                 :            : 
    4809                 :          0 :   condition_edge->flags &= ~EDGE_FALLTHRU;
    4810                 :          0 :   condition_edge->flags |= EDGE_TRUE_VALUE;
    4811                 :          0 :   make_edge (condition_bb, expanded_bb, EDGE_FALSE_VALUE);
    4812                 :            : 
    4813                 :          0 :   redirect_edge_succ (EDGE_SUCC (call_bb, 0), merge_bb);
    4814                 :            : 
    4815                 :          0 :   hsa_cfun->m_modified_cfg = true;
    4816                 :            : 
    4817                 :          0 :   hsa_init_new_bb (expanded_bb);
    4818                 :            : 
    4819                 :            :   /* Slow path: function call.  */
    4820                 :          0 :   gen_hsa_insns_for_direct_call (stmt, hsa_init_new_bb (call_bb), false);
    4821                 :            : 
    4822                 :          0 :   return hsa_bb_for_bb (expanded_bb);
    4823                 :            : }
    4824                 :            : 
    4825                 :            : /* Expand a memory copy BUILTIN (BUILT_IN_MEMCPY, BUILT_IN_MEMPCPY) from
    4826                 :            :    a gimple STMT and store all necessary instruction to HBB basic block.  */
    4827                 :            : 
    4828                 :            : static void
    4829                 :          0 : expand_memory_copy (gimple *stmt, hsa_bb *hbb, enum built_in_function builtin)
    4830                 :            : {
    4831                 :          0 :   tree byte_size = gimple_call_arg (stmt, 2);
    4832                 :            : 
    4833                 :          0 :   if (!tree_fits_uhwi_p (byte_size))
    4834                 :            :     {
    4835                 :          0 :       gen_hsa_insns_for_direct_call (stmt, hbb);
    4836                 :          0 :       return;
    4837                 :            :     }
    4838                 :            : 
    4839                 :          0 :   unsigned HOST_WIDE_INT n = tree_to_uhwi (byte_size);
    4840                 :            : 
    4841                 :          0 :   if (n > HSA_MEMORY_BUILTINS_LIMIT)
    4842                 :            :     {
    4843                 :          0 :       gen_hsa_insns_for_direct_call (stmt, hbb);
    4844                 :          0 :       return;
    4845                 :            :     }
    4846                 :            : 
    4847                 :          0 :   tree dst = gimple_call_arg (stmt, 0);
    4848                 :          0 :   tree src = gimple_call_arg (stmt, 1);
    4849                 :            : 
    4850                 :          0 :   hsa_op_address *dst_addr = get_address_from_value (dst, hbb);
    4851                 :          0 :   hsa_op_address *src_addr = get_address_from_value (src, hbb);
    4852                 :            : 
    4853                 :            :   /* As gen_hsa_memory_copy relies on memory alignment
    4854                 :            :      greater or equal to 8 bytes, we need to verify the alignment.  */
    4855                 :          0 :   BrigType16_t addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
    4856                 :          0 :   hsa_op_reg *src_addr_reg = new hsa_op_reg (addrtype);
    4857                 :          0 :   hsa_op_reg *dst_addr_reg = new hsa_op_reg (addrtype);
    4858                 :            : 
    4859                 :          0 :   convert_addr_to_flat_segment (src_addr, src_addr_reg, hbb);
    4860                 :          0 :   convert_addr_to_flat_segment (dst_addr, dst_addr_reg, hbb);
    4861                 :            : 
    4862                 :            :   /* Process BIT OR for source and destination addresses.  */
    4863                 :          0 :   hsa_op_reg *or_reg = new hsa_op_reg (addrtype);
    4864                 :          0 :   gen_hsa_binary_operation (BRIG_OPCODE_OR, or_reg, src_addr_reg,
    4865                 :            :                             dst_addr_reg, hbb);
    4866                 :            : 
    4867                 :            :   /* Process BIT AND with 0x7 to identify the desired alignment
    4868                 :            :      of 8 bytes.  */
    4869                 :          0 :   hsa_op_reg *masked = new hsa_op_reg (addrtype);
    4870                 :            : 
    4871                 :          0 :   gen_hsa_binary_operation (BRIG_OPCODE_AND, masked, or_reg,
    4872                 :          0 :                             new hsa_op_immed (7, addrtype), hbb);
    4873                 :            : 
    4874                 :          0 :   hsa_op_reg *misaligned = new hsa_op_reg (BRIG_TYPE_B1);
    4875                 :          0 :   hbb->append_insn (new hsa_insn_cmp (BRIG_COMPARE_NE, misaligned->m_type,
    4876                 :            :                                       misaligned, masked,
    4877                 :          0 :                                       new hsa_op_immed (0, masked->m_type)));
    4878                 :            : 
    4879                 :          0 :   hsa_bb *native_impl_bb
    4880                 :          0 :     = expand_string_operation_builtin (stmt, hbb, misaligned);
    4881                 :            : 
    4882                 :          0 :   gen_hsa_memory_copy (native_impl_bb, dst_addr, src_addr, n, BRIG_ALIGNMENT_8);
    4883                 :          0 :   hsa_bb *merge_bb
    4884                 :          0 :     = hsa_init_new_bb (EDGE_SUCC (native_impl_bb->m_bb, 0)->dest);
    4885                 :          0 :   expand_lhs_of_string_op (stmt, n, merge_bb, builtin);
    4886                 :            : }
    4887                 :            : 
    4888                 :            : 
    4889                 :            : /* Expand a memory set BUILTIN (BUILT_IN_MEMSET, BUILT_IN_BZERO) from
    4890                 :            :    a gimple STMT and store all necessary instruction to HBB basic block.
    4891                 :            :    The operation set N bytes with a CONSTANT value.  */
    4892                 :            : 
    4893                 :            : static void
    4894                 :          0 : expand_memory_set (gimple *stmt, unsigned HOST_WIDE_INT n,
    4895                 :            :                    unsigned HOST_WIDE_INT constant, hsa_bb *hbb,
    4896                 :            :                    enum built_in_function builtin)
    4897                 :            : {
    4898                 :          0 :   tree dst = gimple_call_arg (stmt, 0);
    4899                 :          0 :   hsa_op_address *dst_addr = get_address_from_value (dst, hbb);
    4900                 :            : 
    4901                 :            :   /* As gen_hsa_memory_set relies on memory alignment
    4902                 :            :      greater or equal to 8 bytes, we need to verify the alignment.  */
    4903                 :          0 :   BrigType16_t addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
    4904                 :          0 :   hsa_op_reg *dst_addr_reg = new hsa_op_reg (addrtype);
    4905                 :          0 :   convert_addr_to_flat_segment (dst_addr, dst_addr_reg, hbb);
    4906                 :            : 
    4907                 :            :   /* Process BIT AND with 0x7 to identify the desired alignment
    4908                 :            :      of 8 bytes.  */
    4909                 :          0 :   hsa_op_reg *masked = new hsa_op_reg (addrtype);
    4910                 :            : 
    4911                 :          0 :   gen_hsa_binary_operation (BRIG_OPCODE_AND, masked, dst_addr_reg,
    4912                 :          0 :                             new hsa_op_immed (7, addrtype), hbb);
    4913                 :            : 
    4914                 :          0 :   hsa_op_reg *misaligned = new hsa_op_reg (BRIG_TYPE_B1);
    4915                 :          0 :   hbb->append_insn (new hsa_insn_cmp (BRIG_COMPARE_NE, misaligned->m_type,
    4916                 :            :                                       misaligned, masked,
    4917                 :          0 :                                       new hsa_op_immed (0, masked->m_type)));
    4918                 :            : 
    4919                 :          0 :   hsa_bb *native_impl_bb
    4920                 :          0 :     = expand_string_operation_builtin (stmt, hbb, misaligned);
    4921                 :            : 
    4922                 :          0 :   gen_hsa_memory_set (native_impl_bb, dst_addr, constant, n, BRIG_ALIGNMENT_8);
    4923                 :          0 :   hsa_bb *merge_bb
    4924                 :          0 :     = hsa_init_new_bb (EDGE_SUCC (native_impl_bb->m_bb, 0)->dest);
    4925                 :          0 :   expand_lhs_of_string_op (stmt, n, merge_bb, builtin);
    4926                 :          0 : }
    4927                 :            : 
    4928                 :            : /* Store into MEMORDER the memory order specified by tree T, which must be an
    4929                 :            :    integer constant representing a C++ memory order.  If it isn't, issue an HSA
    4930                 :            :    sorry message using LOC and return true, otherwise return false and store
    4931                 :            :    the name of the requested order to *MNAME.  */
    4932                 :            : 
    4933                 :            : static bool
    4934                 :          0 : hsa_memorder_from_tree (tree t, BrigMemoryOrder *memorder, const char **mname,
    4935                 :            :                         location_t loc)
    4936                 :            : {
    4937                 :          0 :   if (!tree_fits_uhwi_p (t))
    4938                 :            :     {
    4939                 :          0 :       HSA_SORRY_ATV (loc, "support for HSA does not implement memory model %E",
    4940                 :            :                      t);
    4941                 :          0 :       return true;
    4942                 :            :     }
    4943                 :            : 
    4944                 :          0 :   unsigned HOST_WIDE_INT mm = tree_to_uhwi (t);
    4945                 :          0 :   switch (mm & MEMMODEL_BASE_MASK)
    4946                 :            :     {
    4947                 :          0 :     case MEMMODEL_RELAXED:
    4948                 :          0 :       *memorder = BRIG_MEMORY_ORDER_RELAXED;
    4949                 :          0 :       *mname = "relaxed";
    4950                 :          0 :       break;
    4951                 :          0 :     case MEMMODEL_CONSUME:
    4952                 :            :       /* HSA does not have an equivalent, but we can use the slightly stronger
    4953                 :            :          ACQUIRE.  */
    4954                 :          0 :       *memorder = BRIG_MEMORY_ORDER_SC_ACQUIRE;
    4955                 :          0 :       *mname = "consume";
    4956                 :          0 :       break;
    4957                 :          0 :     case MEMMODEL_ACQUIRE:
    4958                 :          0 :       *memorder = BRIG_MEMORY_ORDER_SC_ACQUIRE;
    4959                 :          0 :       *mname = "acquire";
    4960                 :          0 :       break;
    4961                 :          0 :     case MEMMODEL_RELEASE:
    4962                 :          0 :       *memorder = BRIG_MEMORY_ORDER_SC_RELEASE;
    4963                 :          0 :       *mname = "release";
    4964                 :          0 :       break;
    4965                 :          0 :     case MEMMODEL_ACQ_REL:
    4966                 :          0 :       *memorder = BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE;
    4967                 :          0 :       *mname = "acq_rel";
    4968                 :          0 :       break;
    4969                 :          0 :     case MEMMODEL_SEQ_CST:
    4970                 :            :       /* Callers implementing a simple load or store need to remove the release
    4971                 :            :          or acquire part respectively.  */
    4972                 :          0 :       *memorder = BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE;
    4973                 :          0 :       *mname = "seq_cst";
    4974                 :          0 :       break;
    4975                 :          0 :     default:
    4976                 :          0 :       {
    4977                 :          0 :         HSA_SORRY_AT (loc, "support for HSA does not implement the specified "
    4978                 :            :                       "memory model");
    4979                 :          0 :         return true;
    4980                 :            :       }
    4981                 :            :     }
    4982                 :            :   return false;
    4983                 :            : }
    4984                 :            : 
    4985                 :            : /* Helper function to create an HSA atomic operation instruction out of calls
    4986                 :            :    to atomic builtins.  RET_ORIG is true if the built-in is the variant that
    4987                 :            :    return s the value before applying operation, and false if it should return
    4988                 :            :    the value after applying the operation (if it returns value at all).  ACODE
    4989                 :            :    is the atomic operation code, STMT is a gimple call to a builtin.  HBB is
    4990                 :            :    the HSA BB to which the instruction should be added.  If SIGNAL is true, the
    4991                 :            :    created operation will work on HSA signals rather than atomic variables.  */
    4992                 :            : 
    4993                 :            : static void
    4994                 :          0 : gen_hsa_atomic_for_builtin (bool ret_orig, enum BrigAtomicOperation acode,
    4995                 :            :                             gimple *stmt, hsa_bb *hbb, bool signal)
    4996                 :            : {
    4997                 :          0 :   tree lhs = gimple_call_lhs (stmt);
    4998                 :            : 
    4999                 :          0 :   tree type = TREE_TYPE (gimple_call_arg (stmt, 1));
    5000                 :          0 :   BrigType16_t hsa_type = hsa_type_for_scalar_tree_type (type, false);
    5001                 :          0 :   BrigType16_t mtype = mem_type_for_type (hsa_type);
    5002                 :          0 :   BrigMemoryOrder memorder;
    5003                 :          0 :   const char *mmname;
    5004                 :            : 
    5005                 :          0 :   if (hsa_memorder_from_tree (gimple_call_arg (stmt, 2), &memorder, &mmname,
    5006                 :            :                               gimple_location (stmt)))
    5007                 :          0 :     return;
    5008                 :            : 
    5009                 :            :   /* Certain atomic insns must have Bx memory types.  */
    5010                 :          0 :   switch (acode)
    5011                 :            :     {
    5012                 :          0 :     case BRIG_ATOMIC_LD:
    5013                 :          0 :     case BRIG_ATOMIC_ST:
    5014                 :          0 :     case BRIG_ATOMIC_AND:
    5015                 :          0 :     case BRIG_ATOMIC_OR:
    5016                 :          0 :     case BRIG_ATOMIC_XOR:
    5017                 :          0 :     case BRIG_ATOMIC_EXCH:
    5018                 :          0 :       mtype = hsa_bittype_for_type (mtype);
    5019                 :          0 :       break;
    5020                 :            :     default:
    5021                 :            :       break;
    5022                 :            :     }
    5023                 :            : 
    5024                 :          0 :   hsa_op_reg *dest;
    5025                 :          0 :   int nops, opcode;
    5026                 :          0 :   if (lhs)
    5027                 :            :     {
    5028                 :          0 :       if (ret_orig)
    5029                 :          0 :         dest = hsa_cfun->reg_for_gimple_ssa (lhs);
    5030                 :            :       else
    5031                 :          0 :         dest = new hsa_op_reg (hsa_type);
    5032                 :          0 :       opcode = signal ? BRIG_OPCODE_SIGNAL : BRIG_OPCODE_ATOMIC;
    5033                 :            :       nops = 3;
    5034                 :            :     }
    5035                 :            :   else
    5036                 :            :     {
    5037                 :          0 :       dest = NULL;
    5038                 :          0 :       opcode = signal ? BRIG_OPCODE_SIGNALNORET : BRIG_OPCODE_ATOMICNORET;
    5039                 :            :       nops = 2;
    5040                 :            :     }
    5041                 :            : 
    5042                 :          0 :   if (acode == BRIG_ATOMIC_ST)
    5043                 :            :     {
    5044                 :          0 :       if (memorder == BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE)
    5045                 :          0 :         memorder = BRIG_MEMORY_ORDER_SC_RELEASE;
    5046                 :            : 
    5047                 :          0 :       if (memorder != BRIG_MEMORY_ORDER_RELAXED
    5048                 :          0 :           && memorder != BRIG_MEMORY_ORDER_SC_RELEASE
    5049                 :          0 :           && memorder != BRIG_MEMORY_ORDER_NONE)
    5050                 :            :         {
    5051                 :          0 :           HSA_SORRY_ATV (gimple_location (stmt),
    5052                 :            :                          "support for HSA does not implement memory model for "
    5053                 :            :                          "%<ATOMIC_ST%>: %s", mmname);
    5054                 :          0 :           return;
    5055                 :            :         }
    5056                 :            :     }
    5057                 :            : 
    5058                 :          0 :   hsa_insn_basic *atominsn;
    5059                 :          0 :   hsa_op_base *tgt;
    5060                 :          0 :   if (signal)
    5061                 :            :     {
    5062                 :          0 :       atominsn = new hsa_insn_signal (nops, opcode, acode, mtype, memorder);
    5063                 :          0 :       tgt = hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 0), hbb);
    5064                 :            :     }
    5065                 :            :   else
    5066                 :            :     {
    5067                 :          0 :       atominsn = new hsa_insn_atomic (nops, opcode, acode, mtype, memorder);
    5068                 :          0 :       hsa_op_address *addr;
    5069                 :          0 :       addr = get_address_from_value (gimple_call_arg (stmt, 0), hbb);
    5070                 :          0 :       if (addr->m_symbol && addr->m_symbol->m_segment == BRIG_SEGMENT_PRIVATE)
    5071                 :            :         {
    5072                 :          0 :           HSA_SORRY_AT (gimple_location (stmt),
    5073                 :            :                         "HSA does not implement atomic operations in private "
    5074                 :            :                         "segment");
    5075                 :          0 :           return;
    5076                 :            :         }
    5077                 :            :       tgt = addr;
    5078                 :            :     }
    5079                 :            : 
    5080                 :          0 :   hsa_op_with_type *op
    5081                 :          0 :     = hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 1), hbb);
    5082                 :          0 :   if (lhs)
    5083                 :            :     {
    5084                 :          0 :       atominsn->set_op (0, dest);
    5085                 :          0 :       atominsn->set_op (1, tgt);
    5086                 :          0 :       atominsn->set_op (2, op);
    5087                 :            :     }
    5088                 :            :   else
    5089                 :            :     {
    5090                 :          0 :       atominsn->set_op (0, tgt);
    5091                 :          0 :       atominsn->set_op (1, op);
    5092                 :            :     }
    5093                 :            : 
    5094                 :          0 :   hbb->append_insn (atominsn);
    5095                 :            : 
    5096                 :            :   /* HSA does not natively support the variants that return the modified value,
    5097                 :            :      so re-do the operation again non-atomically if that is what was
    5098                 :            :      requested.  */
    5099                 :          0 :   if (lhs && !ret_orig)
    5100                 :            :     {
    5101                 :          0 :       int arith;
    5102                 :          0 :       switch (acode)
    5103                 :            :         {
    5104                 :            :         case BRIG_ATOMIC_ADD:
    5105                 :            :           arith = BRIG_OPCODE_ADD;
    5106                 :            :           break;
    5107                 :          0 :         case BRIG_ATOMIC_AND:
    5108                 :          0 :           arith = BRIG_OPCODE_AND;
    5109                 :          0 :           break;
    5110                 :          0 :         case BRIG_ATOMIC_OR:
    5111                 :          0 :           arith = BRIG_OPCODE_OR;
    5112                 :          0 :           break;
    5113                 :          0 :         case BRIG_ATOMIC_SUB:
    5114                 :          0 :           arith = BRIG_OPCODE_SUB;
    5115                 :          0 :           break;
    5116                 :          0 :         case BRIG_ATOMIC_XOR:
    5117                 :          0 :           arith = BRIG_OPCODE_XOR;
    5118                 :          0 :           break;
    5119                 :          0 :         default:
    5120                 :          0 :           gcc_unreachable ();
    5121                 :            :         }
    5122                 :          0 :       hsa_op_reg *real_dest = hsa_cfun->reg_for_gimple_ssa (lhs);
    5123                 :          0 :       gen_hsa_binary_operation (arith, real_dest, dest, op, hbb);
    5124                 :            :     }
    5125                 :            : }
    5126                 :            : 
    5127                 :            : /* Generate HSA instructions for an internal fn.
    5128                 :            :    Instructions will be appended to HBB, which also needs to be the
    5129                 :            :    corresponding structure to the basic_block of STMT.  */
    5130                 :            : 
    5131                 :            : static void
    5132                 :          0 : gen_hsa_insn_for_internal_fn_call (gcall *stmt, hsa_bb *hbb)
    5133                 :            : {
    5134                 :          0 :   gcc_checking_assert (gimple_call_internal_fn (stmt));
    5135                 :          0 :   internal_fn fn = gimple_call_internal_fn (stmt);
    5136                 :            : 
    5137                 :          0 :   bool is_float_type_p = false;
    5138                 :          0 :   if (gimple_call_lhs (stmt) != NULL
    5139                 :          0 :       && TREE_TYPE (gimple_call_lhs (stmt)) == float_type_node)
    5140                 :            :     is_float_type_p = true;
    5141                 :            : 
    5142                 :          0 :   switch (fn)
    5143                 :            :     {
    5144                 :          0 :     case IFN_CEIL:
    5145                 :          0 :       gen_hsa_unaryop_for_builtin (BRIG_OPCODE_CEIL, stmt, hbb);
    5146                 :          0 :       break;
    5147                 :            : 
    5148                 :          0 :     case IFN_FLOOR:
    5149                 :          0 :       gen_hsa_unaryop_for_builtin (BRIG_OPCODE_FLOOR, stmt, hbb);
    5150                 :          0 :       break;
    5151                 :            : 
    5152                 :          0 :     case IFN_RINT:
    5153                 :          0 :       gen_hsa_unaryop_for_builtin (BRIG_OPCODE_RINT, stmt, hbb);
    5154                 :          0 :       break;
    5155                 :            : 
    5156                 :          0 :     case IFN_SQRT:
    5157                 :          0 :       gen_hsa_unaryop_for_builtin (BRIG_OPCODE_SQRT, stmt, hbb);
    5158                 :          0 :       break;
    5159                 :            : 
    5160                 :          0 :     case IFN_RSQRT:
    5161                 :          0 :       gen_hsa_unaryop_for_builtin (BRIG_OPCODE_NRSQRT, stmt, hbb);
    5162                 :          0 :       break;
    5163                 :            : 
    5164                 :          0 :     case IFN_TRUNC:
    5165                 :          0 :       gen_hsa_unaryop_for_builtin (BRIG_OPCODE_TRUNC, stmt, hbb);
    5166                 :          0 :       break;
    5167                 :            : 
    5168                 :          0 :     case IFN_COS:
    5169                 :          0 :       {
    5170                 :          0 :         if (is_float_type_p)
    5171                 :          0 :           gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NCOS, stmt, hbb);
    5172                 :            :         else
    5173                 :          0 :           gen_hsa_unaryop_builtin_call (stmt, hbb);
    5174                 :            : 
    5175                 :            :         break;
    5176                 :            :       }
    5177                 :          0 :     case IFN_EXP2:
    5178                 :          0 :       {
    5179                 :          0 :         if (is_float_type_p)
    5180                 :          0 :           gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NEXP2, stmt, hbb);
    5181                 :            :         else
    5182                 :          0 :           gen_hsa_unaryop_builtin_call (stmt, hbb);
    5183                 :            : 
    5184                 :            :         break;
    5185                 :            :       }
    5186                 :            : 
    5187                 :          0 :     case IFN_LOG2:
    5188                 :          0 :       {
    5189                 :          0 :         if (is_float_type_p)
    5190                 :          0 :           gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NLOG2, stmt, hbb);
    5191                 :            :         else
    5192                 :          0 :           gen_hsa_unaryop_builtin_call (stmt, hbb);
    5193                 :            : 
    5194                 :            :         break;
    5195                 :            :       }
    5196                 :            : 
    5197                 :          0 :     case IFN_SIN:
    5198                 :          0 :       {
    5199                 :          0 :         if (is_float_type_p)
    5200                 :          0 :           gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NSIN, stmt, hbb);
    5201                 :            :         else
    5202                 :          0 :           gen_hsa_unaryop_builtin_call (stmt, hbb);
    5203                 :            :         break;
    5204                 :            :       }
    5205                 :            : 
    5206                 :          0 :     case IFN_CLRSB:
    5207                 :          0 :       gen_hsa_clrsb (stmt, hbb);
    5208                 :          0 :       break;
    5209                 :            : 
    5210                 :          0 :     case IFN_CLZ:
    5211                 :          0 :       gen_hsa_unaryop_for_builtin (BRIG_OPCODE_FIRSTBIT, stmt, hbb);
    5212                 :          0 :       break;
    5213                 :            : 
    5214                 :          0 :     case IFN_CTZ:
    5215                 :          0 :       gen_hsa_unaryop_for_builtin (BRIG_OPCODE_LASTBIT, stmt, hbb);
    5216                 :          0 :       break;
    5217                 :            : 
    5218                 :          0 :     case IFN_FFS:
    5219                 :          0 :       gen_hsa_ffs (stmt, hbb);
    5220                 :          0 :       break;
    5221                 :            : 
    5222                 :          0 :     case IFN_PARITY:
    5223                 :          0 :       gen_hsa_parity (stmt, hbb);
    5224                 :          0 :       break;
    5225                 :            : 
    5226                 :          0 :     case IFN_POPCOUNT:
    5227                 :          0 :       gen_hsa_popcount (stmt, hbb);
    5228                 :          0 :       break;
    5229                 :            : 
    5230                 :          0 :     case IFN_DIVMOD:
    5231                 :          0 :       gen_hsa_divmod (stmt, hbb);
    5232                 :          0 :       break;
    5233                 :            : 
    5234                 :          0 :     case IFN_ACOS:
    5235                 :          0 :     case IFN_ASIN:
    5236                 :          0 :     case IFN_ATAN:
    5237                 :          0 :     case IFN_EXP:
    5238                 :          0 :     case IFN_EXP10:
    5239                 :          0 :     case IFN_EXPM1:
    5240                 :          0 :     case IFN_LOG:
    5241                 :          0 :     case IFN_LOG10:
    5242                 :          0 :     case IFN_LOG1P:
    5243                 :          0 :     case IFN_LOGB:
    5244                 :          0 :     case IFN_SIGNIFICAND:
    5245                 :          0 :     case IFN_TAN:
    5246                 :          0 :     case IFN_NEARBYINT:
    5247                 :          0 :     case IFN_ROUND:
    5248                 :          0 :     case IFN_ATAN2:
    5249                 :          0 :     case IFN_COPYSIGN:
    5250                 :          0 :     case IFN_FMOD:
    5251                 :          0 :     case IFN_POW:
    5252                 :          0 :     case IFN_REMAINDER:
    5253                 :          0 :     case IFN_SCALB:
    5254                 :          0 :     case IFN_FMIN:
    5255                 :          0 :     case IFN_FMAX:
    5256                 :          0 :       gen_hsa_insns_for_call_of_internal_fn (stmt, hbb);
    5257                 :          0 :       break;
    5258                 :            : 
    5259                 :          0 :     case IFN_FMA:
    5260                 :          0 :       gen_hsa_fma (stmt, hbb, false, false);
    5261                 :          0 :       break;
    5262                 :            : 
    5263                 :          0 :     case IFN_FMS:
    5264                 :          0 :       gen_hsa_fma (stmt, hbb, false, true);
    5265                 :          0 :       break;
    5266                 :            : 
    5267                 :          0 :     case IFN_FNMA:
    5268                 :          0 :       gen_hsa_fma (stmt, hbb, true, false);
    5269                 :          0 :       break;
    5270                 :            : 
    5271                 :          0 :     case IFN_FNMS:
    5272                 :          0 :       gen_hsa_fma (stmt, hbb, true, true);
    5273                 :          0 :       break;
    5274                 :            : 
    5275                 :          0 :     default:
    5276                 :          0 :       HSA_SORRY_ATV (gimple_location (stmt),
    5277                 :            :                      "support for HSA does not implement internal function: %s",
    5278                 :            :                      internal_fn_name (fn));
    5279                 :          0 :       break;
    5280                 :            :     }
    5281                 :          0 : }
    5282                 :            : 
    5283                 :            : /* Generate HSA instructions for the given call statement STMT.  Instructions
    5284                 :            :    will be appended to HBB.  */
    5285                 :            : 
    5286                 :            : static void
    5287                 :          0 : gen_hsa_insns_for_call (gimple *stmt, hsa_bb *hbb)
    5288                 :            : {
    5289                 :          0 :   gcall *call = as_a <gcall *> (stmt);
    5290                 :          0 :   tree lhs = gimple_call_lhs (stmt);
    5291                 :          0 :   hsa_op_reg *dest;
    5292                 :            : 
    5293                 :          0 :   if (gimple_call_internal_p (stmt))
    5294                 :            :     {
    5295                 :          0 :       gen_hsa_insn_for_internal_fn_call (call, hbb);
    5296                 :          0 :       return;
    5297                 :            :     }
    5298                 :            : 
    5299                 :          0 :   if (!gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
    5300                 :            :     {
    5301                 :          0 :       tree function_decl = gimple_call_fndecl (stmt);
    5302                 :            :       /* Prefetch pass can create type-mismatching prefetch builtin calls which
    5303                 :            :          fail the gimple_call_builtin_p test above.  Handle them here.  */
    5304                 :          0 :       if (fndecl_built_in_p (function_decl, BUILT_IN_PREFETCH))
    5305                 :            :         return;
    5306                 :            : 
    5307                 :          0 :       if (function_decl == NULL_TREE)
    5308                 :            :         {
    5309                 :          0 :           HSA_SORRY_AT (gimple_location (stmt),
    5310                 :            :                         "support for HSA does not implement indirect calls");
    5311                 :          0 :           return;
    5312                 :            :         }
    5313                 :            : 
    5314                 :          0 :       if (hsa_callable_function_p (function_decl))
    5315                 :          0 :         gen_hsa_insns_for_direct_call (stmt, hbb);
    5316                 :          0 :       else if (!gen_hsa_insns_for_known_library_call (stmt, hbb))
    5317                 :          0 :         HSA_SORRY_AT (gimple_location (stmt),
    5318                 :            :                       "HSA supports only calls of functions marked with "
    5319                 :            :                       "%<#pragma omp declare target%>");
    5320                 :          0 :       return;
    5321                 :            :     }
    5322                 :            : 
    5323                 :          0 :   tree fndecl = gimple_call_fndecl (stmt);
    5324                 :          0 :   enum built_in_function builtin = DECL_FUNCTION_CODE (fndecl);
    5325                 :          0 :   switch (builtin)
    5326                 :            :     {
    5327                 :          0 :     case BUILT_IN_FABS:
    5328                 :          0 :     case BUILT_IN_FABSF:
    5329                 :          0 :       gen_hsa_unaryop_for_builtin (BRIG_OPCODE_ABS, stmt, hbb);
    5330                 :          0 :       break;
    5331                 :            : 
    5332                 :          0 :     case BUILT_IN_CEIL:
    5333                 :          0 :     case BUILT_IN_CEILF:
    5334                 :          0 :       gen_hsa_unaryop_for_builtin (BRIG_OPCODE_CEIL, stmt, hbb);
    5335                 :          0 :       break;
    5336                 :            : 
    5337                 :          0 :     case BUILT_IN_FLOOR:
    5338                 :          0 :     case BUILT_IN_FLOORF:
    5339                 :          0 :       gen_hsa_unaryop_for_builtin (BRIG_OPCODE_FLOOR, stmt, hbb);
    5340                 :          0 :       break;
    5341                 :            : 
    5342                 :          0 :     case BUILT_IN_RINT:
    5343                 :          0 :     case BUILT_IN_RINTF:
    5344                 :          0 :       gen_hsa_unaryop_for_builtin (BRIG_OPCODE_RINT, stmt, hbb);
    5345                 :          0 :       break;
    5346                 :            : 
    5347                 :          0 :     case BUILT_IN_SQRT:
    5348                 :          0 :     case BUILT_IN_SQRTF:
    5349                 :          0 :       gen_hsa_unaryop_for_builtin (BRIG_OPCODE_SQRT, stmt, hbb);
    5350                 :          0 :       break;
    5351                 :            : 
    5352                 :          0 :     case BUILT_IN_TRUNC:
    5353                 :          0 :     case BUILT_IN_TRUNCF:
    5354                 :          0 :       gen_hsa_unaryop_for_builtin (BRIG_OPCODE_TRUNC, stmt, hbb);
    5355                 :          0 :       break;
    5356                 :            : 
    5357                 :          0 :     case BUILT_IN_COS:
    5358                 :          0 :     case BUILT_IN_SIN:
    5359                 :          0 :     case BUILT_IN_EXP2:
    5360                 :          0 :     case BUILT_IN_LOG2:
    5361                 :            :       /* HSAIL does not provide an instruction for double argument type.  */
    5362                 :          0 :       gen_hsa_unaryop_builtin_call (stmt, hbb);
    5363                 :          0 :       break;
    5364                 :            : 
    5365                 :          0 :     case BUILT_IN_COSF:
    5366                 :          0 :       gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NCOS, stmt, hbb);
    5367                 :          0 :       break;
    5368                 :            : 
    5369                 :          0 :     case BUILT_IN_EXP2F:
    5370                 :          0 :       gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NEXP2, stmt, hbb);
    5371                 :          0 :       break;
    5372                 :            : 
    5373                 :          0 :     case BUILT_IN_LOG2F:
    5374                 :          0 :       gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NLOG2, stmt, hbb);
    5375                 :          0 :       break;
    5376                 :            : 
    5377                 :          0 :     case BUILT_IN_SINF:
    5378                 :          0 :       gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NSIN, stmt, hbb);
    5379                 :          0 :       break;
    5380                 :            : 
    5381                 :          0 :     case BUILT_IN_CLRSB:
    5382                 :          0 :     case BUILT_IN_CLRSBL:
    5383                 :          0 :     case BUILT_IN_CLRSBLL:
    5384                 :          0 :       gen_hsa_clrsb (call, hbb);
    5385                 :          0 :       break;
    5386                 :            : 
    5387                 :          0 :     case BUILT_IN_CLZ:
    5388                 :          0 :     case BUILT_IN_CLZL:
    5389                 :          0 :     case BUILT_IN_CLZLL:
    5390                 :          0 :       gen_hsa_unaryop_for_builtin (BRIG_OPCODE_FIRSTBIT, stmt, hbb);
    5391                 :          0 :       break;
    5392                 :            : 
    5393                 :          0 :     case BUILT_IN_CTZ:
    5394                 :          0 :     case BUILT_IN_CTZL:
    5395                 :          0 :     case BUILT_IN_CTZLL:
    5396                 :          0 :       gen_hsa_unaryop_for_builtin (BRIG_OPCODE_LASTBIT, stmt, hbb);
    5397                 :          0 :       break;
    5398                 :            : 
    5399                 :          0 :     case BUILT_IN_FFS:
    5400                 :          0 :     case BUILT_IN_FFSL:
    5401                 :          0 :     case BUILT_IN_FFSLL:
    5402                 :          0 :       gen_hsa_ffs (call, hbb);
    5403                 :          0 :       break;
    5404                 :            : 
    5405                 :          0 :     case BUILT_IN_PARITY:
    5406                 :          0 :     case BUILT_IN_PARITYL:
    5407                 :          0 :     case BUILT_IN_PARITYLL:
    5408                 :          0 :       gen_hsa_parity (call, hbb);
    5409                 :          0 :       break;
    5410                 :            : 
    5411                 :          0 :     case BUILT_IN_POPCOUNT:
    5412                 :          0 :     case BUILT_IN_POPCOUNTL:
    5413                 :          0 :     case BUILT_IN_POPCOUNTLL:
    5414                 :          0 :       gen_hsa_popcount (call, hbb);
    5415                 :          0 :       break;
    5416                 :            : 
    5417                 :          0 :     case BUILT_IN_ATOMIC_LOAD_1:
    5418                 :          0 :     case BUILT_IN_ATOMIC_LOAD_2:
    5419                 :          0 :     case BUILT_IN_ATOMIC_LOAD_4:
    5420                 :          0 :     case BUILT_IN_ATOMIC_LOAD_8:
    5421                 :          0 :     case BUILT_IN_ATOMIC_LOAD_16:
    5422                 :          0 :       {
    5423                 :          0 :         BrigType16_t mtype;
    5424                 :          0 :         hsa_op_base *src;
    5425                 :          0 :         src = get_address_from_value (gimple_call_arg (stmt, 0), hbb);
    5426                 :            : 
    5427                 :          0 :         BrigMemoryOrder memorder;
    5428                 :          0 :         const char *mmname;
    5429                 :          0 :         if (hsa_memorder_from_tree (gimple_call_arg (stmt, 1), &memorder,
    5430                 :            :                                     &mmname, gimple_location (stmt)))
    5431                 :          0 :           return;
    5432                 :            : 
    5433                 :          0 :         if (memorder == BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE)
    5434                 :          0 :           memorder = BRIG_MEMORY_ORDER_SC_ACQUIRE;
    5435                 :            : 
    5436                 :          0 :         if (memorder != BRIG_MEMORY_ORDER_RELAXED
    5437                 :            :             && memorder != BRIG_MEMORY_ORDER_SC_ACQUIRE
    5438                 :          0 :             && memorder != BRIG_MEMORY_ORDER_NONE)
    5439                 :            :           {
    5440                 :          0 :             HSA_SORRY_ATV (gimple_location (stmt),
    5441                 :            :                            "support for HSA does not implement "
    5442                 :            :                            "memory model for atomic loads: %s", mmname);
    5443                 :          0 :             return;
    5444                 :            :           }
    5445                 :            : 
    5446                 :          0 :         if (lhs)
    5447                 :            :           {
    5448                 :          0 :             BrigType16_t t = hsa_type_for_scalar_tree_type (TREE_TYPE (lhs),
    5449                 :            :                                                             false);
    5450                 :          0 :             mtype = mem_type_for_type (t);
    5451                 :          0 :             mtype = hsa_bittype_for_type (mtype);
    5452                 :          0 :             dest = hsa_cfun->reg_for_gimple_ssa (lhs);
    5453                 :            :           }
    5454                 :            :         else
    5455                 :            :           {
    5456                 :          0 :             mtype = BRIG_TYPE_B64;
    5457                 :          0 :             dest = new hsa_op_reg (mtype);
    5458                 :            :           }
    5459                 :            : 
    5460                 :          0 :         hsa_insn_basic *atominsn;
    5461                 :          0 :         atominsn = new hsa_insn_atomic (2, BRIG_OPCODE_ATOMIC, BRIG_ATOMIC_LD,
    5462                 :          0 :                                         mtype, memorder, dest, src);
    5463                 :            : 
    5464                 :          0 :         hbb->append_insn (atominsn);
    5465                 :          0 :         break;
    5466                 :            :       }
    5467                 :            : 
    5468                 :          0 :     case BUILT_IN_ATOMIC_EXCHANGE_1:
    5469                 :          0 :     case BUILT_IN_ATOMIC_EXCHANGE_2:
    5470                 :          0 :     case BUILT_IN_ATOMIC_EXCHANGE_4:
    5471                 :          0 :     case BUILT_IN_ATOMIC_EXCHANGE_8:
    5472                 :          0 :     case BUILT_IN_ATOMIC_EXCHANGE_16:
    5473                 :          0 :       gen_hsa_atomic_for_builtin (true, BRIG_ATOMIC_EXCH, stmt, hbb, false);
    5474                 :          0 :       break;
    5475                 :            :       break;
    5476                 :            : 
    5477                 :          0 :     case BUILT_IN_ATOMIC_FETCH_ADD_1:
    5478                 :          0 :     case BUILT_IN_ATOMIC_FETCH_ADD_2:
    5479                 :          0 :     case BUILT_IN_ATOMIC_FETCH_ADD_4:
    5480                 :          0 :     case BUILT_IN_ATOMIC_FETCH_ADD_8:
    5481                 :          0 :     case BUILT_IN_ATOMIC_FETCH_ADD_16:
    5482                 :          0 :       gen_hsa_atomic_for_builtin (true, BRIG_ATOMIC_ADD, stmt, hbb, false);
    5483                 :          0 :       break;
    5484                 :            :       break;
    5485                 :            : 
    5486                 :          0 :     case BUILT_IN_ATOMIC_FETCH_SUB_1:
    5487                 :          0 :     case BUILT_IN_ATOMIC_FETCH_SUB_2:
    5488                 :          0 :     case BUILT_IN_ATOMIC_FETCH_SUB_4:
    5489                 :          0 :     case BUILT_IN_ATOMIC_FETCH_SUB_8:
    5490                 :          0 :     case BUILT_IN_ATOMIC_FETCH_SUB_16:
    5491                 :          0 :       gen_hsa_atomic_for_builtin (true, BRIG_ATOMIC_SUB, stmt, hbb, false);
    5492                 :          0 :       break;
    5493                 :            :       break;
    5494                 :            : 
    5495                 :          0 :     case BUILT_IN_ATOMIC_FETCH_AND_1:
    5496                 :          0 :     case BUILT_IN_ATOMIC_FETCH_AND_2:
    5497                 :          0 :     case BUILT_IN_ATOMIC_FETCH_AND_4:
    5498                 :          0 :     case BUILT_IN_ATOMIC_FETCH_AND_8:
    5499                 :          0 :     case BUILT_IN_ATOMIC_FETCH_AND_16:
    5500                 :          0 :       gen_hsa_atomic_for_builtin (true, BRIG_ATOMIC_AND, stmt, hbb, false);
    5501                 :          0 :       break;
    5502                 :            :       break;
    5503                 :            : 
    5504                 :          0 :     case BUILT_IN_ATOMIC_FETCH_XOR_1:
    5505                 :          0 :     case BUILT_IN_ATOMIC_FETCH_XOR_2:
    5506                 :          0 :     case BUILT_IN_ATOMIC_FETCH_XOR_4:
    5507                 :          0 :     case BUILT_IN_ATOMIC_FETCH_XOR_8:
    5508                 :          0 :     case BUILT_IN_ATOMIC_FETCH_XOR_16:
    5509                 :          0 :       gen_hsa_atomic_for_builtin (true, BRIG_ATOMIC_XOR, stmt, hbb, false);
    5510                 :          0 :       break;
    5511                 :            :       break;
    5512                 :            : 
    5513                 :          0 :     case BUILT_IN_ATOMIC_FETCH_OR_1:
    5514                 :          0 :     case BUILT_IN_ATOMIC_FETCH_OR_2:
    5515                 :          0 :     case BUILT_IN_ATOMIC_FETCH_OR_4:
    5516                 :          0 :     case BUILT_IN_ATOMIC_FETCH_OR_8:
    5517                 :          0 :     case BUILT_IN_ATOMIC_FETCH_OR_16:
    5518                 :          0 :       gen_hsa_atomic_for_builtin (true, BRIG_ATOMIC_OR, stmt, hbb, false);
    5519                 :          0 :       break;
    5520                 :            :       break;
    5521                 :            : 
    5522                 :          0 :     case BUILT_IN_ATOMIC_STORE_1:
    5523                 :          0 :     case BUILT_IN_ATOMIC_STORE_2:
    5524                 :          0 :     case BUILT_IN_ATOMIC_STORE_4:
    5525                 :          0 :     case BUILT_IN_ATOMIC_STORE_8:
    5526                 :          0 :     case BUILT_IN_ATOMIC_STORE_16:
    5527                 :            :       /* Since there cannot be any LHS, the first parameter is meaningless.  */
    5528                 :          0 :       gen_hsa_atomic_for_builtin (true, BRIG_ATOMIC_ST, stmt, hbb, false);
    5529                 :          0 :       break;
    5530                 :            :       break;
    5531                 :            : 
    5532                 :          0 :     case BUILT_IN_ATOMIC_ADD_FETCH_1:
    5533                 :          0 :     case BUILT_IN_ATOMIC_ADD_FETCH_2:
    5534                 :          0 :     case BUILT_IN_ATOMIC_ADD_FETCH_4:
    5535                 :          0 :     case BUILT_IN_ATOMIC_ADD_FETCH_8:
    5536                 :          0 :     case BUILT_IN_ATOMIC_ADD_FETCH_16:
    5537                 :          0 :       gen_hsa_atomic_for_builtin (false, BRIG_ATOMIC_ADD, stmt, hbb, false);
    5538                 :          0 :       break;
    5539                 :            : 
    5540                 :          0 :     case BUILT_IN_ATOMIC_SUB_FETCH_1:
    5541                 :          0 :     case BUILT_IN_ATOMIC_SUB_FETCH_2:
    5542                 :          0 :     case BUILT_IN_ATOMIC_SUB_FETCH_4:
    5543                 :          0 :     case BUILT_IN_ATOMIC_SUB_FETCH_8:
    5544                 :          0 :     case BUILT_IN_ATOMIC_SUB_FETCH_16:
    5545                 :          0 :       gen_hsa_atomic_for_builtin (false, BRIG_ATOMIC_SUB, stmt, hbb, false);
    5546                 :          0 :       break;
    5547                 :            : 
    5548                 :          0 :     case BUILT_IN_ATOMIC_AND_FETCH_1:
    5549                 :          0 :     case BUILT_IN_ATOMIC_AND_FETCH_2:
    5550                 :          0 :     case BUILT_IN_ATOMIC_AND_FETCH_4:
    5551                 :          0 :     case BUILT_IN_ATOMIC_AND_FETCH_8:
    5552                 :          0 :     case BUILT_IN_ATOMIC_AND_FETCH_16:
    5553                 :          0 :       gen_hsa_atomic_for_builtin (false, BRIG_ATOMIC_AND, stmt, hbb, false);
    5554                 :          0 :       break;
    5555                 :            : 
    5556                 :          0 :     case BUILT_IN_ATOMIC_XOR_FETCH_1:
    5557                 :          0 :     case BUILT_IN_ATOMIC_XOR_FETCH_2:
    5558                 :          0 :     case BUILT_IN_ATOMIC_XOR_FETCH_4:
    5559                 :          0 :     case BUILT_IN_ATOMIC_XOR_FETCH_8:
    5560                 :          0 :     case BUILT_IN_ATOMIC_XOR_FETCH_16:
    5561                 :          0 :       gen_hsa_atomic_for_builtin (false, BRIG_ATOMIC_XOR, stmt, hbb, false);
    5562                 :          0 :       break;
    5563                 :            : 
    5564                 :          0 :     case BUILT_IN_ATOMIC_OR_FETCH_1:
    5565                 :          0 :     case BUILT_IN_ATOMIC_OR_FETCH_2:
    5566                 :          0 :     case BUILT_IN_ATOMIC_OR_FETCH_4:
    5567                 :          0 :     case BUILT_IN_ATOMIC_OR_FETCH_8:
    5568                 :          0 :     case BUILT_IN_ATOMIC_OR_FETCH_16:
    5569                 :          0 :       gen_hsa_atomic_for_builtin (false, BRIG_ATOMIC_OR, stmt, hbb, false);
    5570                 :          0 :       break;
    5571                 :            : 
    5572                 :          0 :     case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_1:
    5573                 :          0 :     case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_2:
    5574                 :          0 :     case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_4:
    5575                 :          0 :     case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_8:
    5576                 :          0 :     case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_16:
    5577                 :          0 :       {
    5578                 :          0 :         tree type = TREE_TYPE (gimple_call_arg (stmt, 1));
    5579                 :          0 :         BrigType16_t atype
    5580                 :          0 :           = hsa_bittype_for_type (hsa_type_for_scalar_tree_type (type, false));
    5581                 :          0 :         BrigMemoryOrder memorder = BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE;
    5582                 :          0 :         hsa_insn_basic *atominsn;
    5583                 :          0 :         hsa_op_base *tgt;
    5584                 :          0 :         atominsn = new hsa_insn_atomic (4, BRIG_OPCODE_ATOMIC,
    5585                 :          0 :                                         BRIG_ATOMIC_CAS, atype, memorder);
    5586                 :          0 :         tgt = get_address_from_value (gimple_call_arg (stmt, 0), hbb);
    5587                 :            : 
    5588                 :          0 :         if (lhs != NULL)
    5589                 :          0 :           dest = hsa_cfun->reg_for_gimple_ssa (lhs);
    5590                 :            :         else
    5591                 :          0 :           dest = new hsa_op_reg (atype);
    5592                 :            : 
    5593                 :          0 :         atominsn->set_op (0, dest);
    5594                 :          0 :         atominsn->set_op (1, tgt);
    5595                 :            : 
    5596                 :          0 :         hsa_op_with_type *op
    5597                 :          0 :           = hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 1), hbb);
    5598                 :          0 :         atominsn->set_op (2, op);
    5599                 :          0 :         op = hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 2), hbb);
    5600                 :          0 :         atominsn->set_op (3, op);
    5601                 :            : 
    5602                 :          0 :         hbb->append_insn (atominsn);
    5603                 :          0 :         break;
    5604                 :            :       }
    5605                 :            : 
    5606                 :          0 :     case BUILT_IN_HSA_WORKGROUPID:
    5607                 :          0 :       query_hsa_grid_dim (stmt, BRIG_OPCODE_WORKGROUPID, hbb);
    5608                 :          0 :       break;
    5609                 :          0 :     case BUILT_IN_HSA_WORKITEMID:
    5610                 :          0 :       query_hsa_grid_dim (stmt, BRIG_OPCODE_WORKITEMID, hbb);
    5611                 :          0 :       break;
    5612                 :          0 :     case BUILT_IN_HSA_WORKITEMABSID:
    5613                 :          0 :       query_hsa_grid_dim (stmt, BRIG_OPCODE_WORKITEMABSID, hbb);
    5614                 :          0 :       break;
    5615                 :          0 :     case BUILT_IN_HSA_GRIDSIZE:
    5616                 :          0 :       query_hsa_grid_dim (stmt, BRIG_OPCODE_GRIDSIZE, hbb);
    5617                 :          0 :       break;
    5618                 :          0 :     case BUILT_IN_HSA_CURRENTWORKGROUPSIZE:
    5619                 :          0 :       query_hsa_grid_dim (stmt, BRIG_OPCODE_CURRENTWORKGROUPSIZE, hbb);
    5620                 :          0 :       break;
    5621                 :            : 
    5622                 :          0 :     case BUILT_IN_GOMP_BARRIER:
    5623                 :          0 :       hbb->append_insn (new hsa_insn_br (0, BRIG_OPCODE_BARRIER, BRIG_TYPE_NONE,
    5624                 :          0 :                                          BRIG_WIDTH_ALL));
    5625                 :          0 :       break;
    5626                 :          0 :     case BUILT_IN_GOMP_PARALLEL:
    5627                 :          0 :       HSA_SORRY_AT (gimple_location (stmt),
    5628                 :            :                     "support for HSA does not implement non-gridified "
    5629                 :            :                     "OpenMP parallel constructs");
    5630                 :          0 :       break;
    5631                 :            : 
    5632                 :          0 :     case BUILT_IN_OMP_GET_THREAD_NUM:
    5633                 :          0 :       {
    5634                 :          0 :         query_hsa_grid_nodim (stmt, BRIG_OPCODE_WORKITEMFLATABSID, hbb);
    5635                 :          0 :         break;
    5636                 :            :       }
    5637                 :            : 
    5638                 :          0 :     case BUILT_IN_OMP_GET_NUM_THREADS:
    5639                 :          0 :       {
    5640                 :          0 :         gen_get_num_threads (stmt, hbb);
    5641                 :          0 :         break;
    5642                 :            :       }
    5643                 :          0 :     case BUILT_IN_GOMP_TEAMS:
    5644                 :          0 :       {
    5645                 :          0 :         gen_set_num_threads (gimple_call_arg (stmt, 1), hbb);
    5646                 :          0 :         break;
    5647                 :            :       }
    5648                 :          0 :     case BUILT_IN_OMP_GET_NUM_TEAMS:
    5649                 :          0 :       {
    5650                 :          0 :         gen_get_num_teams (stmt, hbb);
    5651                 :          0 :         break;
    5652                 :            :       }
    5653                 :          0 :     case BUILT_IN_OMP_GET_TEAM_NUM:
    5654                 :          0 :       {
    5655                 :          0 :         gen_get_team_num (stmt, hbb);
    5656                 :          0 :         break;
    5657                 :            :       }
    5658                 :          0 :     case BUILT_IN_MEMCPY:
    5659                 :          0 :     case BUILT_IN_MEMPCPY:
    5660                 :          0 :       {
    5661                 :          0 :         expand_memory_copy (stmt, hbb, builtin);
    5662                 :          0 :         break;
    5663                 :            :       }
    5664                 :          0 :     case BUILT_IN_MEMSET:
    5665                 :          0 :       {
    5666                 :          0 :         tree c = gimple_call_arg (stmt, 1);
    5667                 :            : 
    5668                 :          0 :         if (TREE_CODE (c) != INTEGER_CST)
    5669                 :            :           {
    5670                 :          0 :             gen_hsa_insns_for_direct_call (stmt, hbb);
    5671                 :          0 :             return;
    5672                 :            :           }
    5673                 :            : 
    5674                 :          0 :         tree byte_size = gimple_call_arg (stmt, 2);
    5675                 :            : 
    5676                 :          0 :         if (!tree_fits_uhwi_p (byte_size))
    5677                 :            :           {
    5678                 :          0 :             gen_hsa_insns_for_direct_call (stmt, hbb);
    5679                 :          0 :             return;
    5680                 :            :           }
    5681                 :            : 
    5682                 :          0 :         unsigned HOST_WIDE_INT n = tree_to_uhwi (byte_size);
    5683                 :            : 
    5684                 :          0 :         if (n > HSA_MEMORY_BUILTINS_LIMIT)
    5685                 :            :           {
    5686                 :          0 :             gen_hsa_insns_for_direct_call (stmt, hbb);
    5687                 :          0 :             return;
    5688                 :            :           }
    5689                 :            : 
    5690                 :          0 :         unsigned HOST_WIDE_INT constant
    5691                 :          0 :           = tree_to_uhwi (fold_convert (unsigned_char_type_node, c));
    5692                 :            : 
    5693                 :          0 :         expand_memory_set (stmt, n, constant, hbb, builtin);
    5694                 :            : 
    5695                 :          0 :         break;
    5696                 :            :       }
    5697                 :          0 :     case BUILT_IN_BZERO:
    5698                 :          0 :       {
    5699                 :          0 :         tree byte_size = gimple_call_arg (stmt, 1);
    5700                 :            : 
    5701                 :          0 :         if (!tree_fits_uhwi_p (byte_size))
    5702                 :            :           {
    5703                 :          0 :             gen_hsa_insns_for_direct_call (stmt, hbb);
    5704                 :          0 :             return;
    5705                 :            :           }
    5706                 :            : 
    5707                 :          0 :         unsigned HOST_WIDE_INT n = tree_to_uhwi (byte_size);
    5708                 :            : 
    5709                 :          0 :         if (n > HSA_MEMORY_BUILTINS_LIMIT)
    5710                 :            :           {
    5711                 :          0 :             gen_hsa_insns_for_direct_call (stmt, hbb);
    5712                 :          0 :             return;
    5713                 :            :           }
    5714                 :            : 
    5715                 :          0 :         expand_memory_set (stmt, n, 0, hbb, builtin);
    5716                 :            : 
    5717                 :          0 :         break;
    5718                 :            :       }
    5719                 :          0 :     CASE_BUILT_IN_ALLOCA:
    5720                 :          0 :       {
    5721                 :          0 :         gen_hsa_alloca (call, hbb);
    5722                 :          0 :         break;
    5723                 :            :       }
    5724                 :            :     case BUILT_IN_PREFETCH:
    5725                 :            :       break;
    5726                 :          0 :     default:
    5727                 :          0 :       {
    5728                 :          0 :         tree name_tree = DECL_NAME (fndecl);
    5729                 :          0 :         const char *s = IDENTIFIER_POINTER (name_tree);
    5730                 :          0 :         size_t len = strlen (s);
    5731                 :          0 :         if (len > 4 && (strncmp (s, "__builtin_GOMP_", 15) == 0))
    5732                 :          0 :           HSA_SORRY_ATV (gimple_location (stmt),
    5733                 :            :                          "support for HSA does not implement GOMP function %s",
    5734                 :          0 :                          s);
    5735                 :            :         else
    5736                 :          0 :           gen_hsa_insns_for_direct_call (stmt, hbb);
    5737                 :            :         return;
    5738                 :            :       }
    5739                 :            :     }
    5740                 :            : }
    5741                 :            : 
    5742                 :            : /* Generate HSA instructions for a given gimple statement.  Instructions will be
    5743                 :            :    appended to HBB.  */
    5744                 :            : 
    5745                 :            : static void
    5746                 :          0 : gen_hsa_insns_for_gimple_stmt (gimple *stmt, hsa_bb *hbb)
    5747                 :            : {
    5748                 :          0 :   switch (gimple_code (stmt))
    5749                 :            :     {
    5750                 :          0 :     case GIMPLE_ASSIGN:
    5751                 :          0 :       if (gimple_clobber_p (stmt))
    5752                 :            :         break;
    5753                 :            : 
    5754                 :          0 :       if (gimple_assign_single_p (stmt))
    5755                 :            :         {
    5756                 :          0 :           tree lhs = gimple_assign_lhs (stmt);
    5757                 :          0 :           tree rhs = gimple_assign_rhs1 (stmt);
    5758                 :          0 :           gen_hsa_insns_for_single_assignment (lhs, rhs, hbb);
    5759                 :            :         }
    5760                 :            :       else
    5761                 :          0 :         gen_hsa_insns_for_operation_assignment (stmt, hbb);
    5762                 :            :       break;
    5763                 :          0 :     case GIMPLE_RETURN:
    5764                 :          0 :       gen_hsa_insns_for_return (as_a <greturn *> (stmt), hbb);
    5765                 :          0 :       break;
    5766                 :          0 :     case GIMPLE_COND:
    5767                 :          0 :       gen_hsa_insns_for_cond_stmt (stmt, hbb);
    5768                 :          0 :       break;
    5769                 :          0 :     case GIMPLE_CALL:
    5770                 :          0 :       gen_hsa_insns_for_call (stmt, hbb);
    5771                 :          0 :       break;
    5772                 :            :     case GIMPLE_DEBUG:
    5773                 :            :       /* ??? HSA supports some debug facilities.  */
    5774                 :            :       break;
    5775                 :          0 :     case GIMPLE_LABEL:
    5776                 :          0 :     {
    5777                 :          0 :       tree label = gimple_label_label (as_a <glabel *> (stmt));
    5778                 :          0 :       if (FORCED_LABEL (label))
    5779                 :          0 :         HSA_SORRY_AT (gimple_location (stmt),
    5780                 :            :                       "support for HSA does not implement gimple label with "
    5781                 :            :                       "address taken");
    5782                 :            : 
    5783                 :            :       break;
    5784                 :            :     }
    5785                 :          0 :     case GIMPLE_NOP:
    5786                 :          0 :     {
    5787                 :          0 :       hbb->append_insn (new hsa_insn_basic (0, BRIG_OPCODE_NOP));
    5788                 :          0 :       break;
    5789                 :            :     }
    5790                 :          0 :     case GIMPLE_SWITCH:
    5791                 :          0 :     {
    5792                 :          0 :       gen_hsa_insns_for_switch_stmt (as_a <gswitch *> (stmt), hbb);
    5793                 :          0 :       break;
    5794                 :            :     }
    5795                 :          0 :     default:
    5796                 :          0 :       HSA_SORRY_ATV (gimple_location (stmt),
    5797                 :            :                      "support for HSA does not implement gimple statement %s",
    5798                 :            :                      gimple_code_name[(int) gimple_code (stmt)]);
    5799                 :            :     }
    5800                 :          0 : }
    5801                 :            : 
    5802                 :            : /* Generate a HSA PHI from a gimple PHI.  */
    5803                 :            : 
    5804                 :            : static void
    5805                 :          0 : gen_hsa_phi_from_gimple_phi (gimple *phi_stmt, hsa_bb *hbb)
    5806                 :            : {
    5807                 :          0 :   hsa_insn_phi *hphi;
    5808                 :          0 :   unsigned count = gimple_phi_num_args (phi_stmt);
    5809                 :            : 
    5810                 :          0 :   hsa_op_reg *dest
    5811                 :          0 :     = hsa_cfun->reg_for_gimple_ssa (gimple_phi_result (phi_stmt));
    5812                 :          0 :   hphi = new hsa_insn_phi (count, dest);
    5813                 :          0 :   hphi->m_bb = hbb->m_bb;
    5814                 :            : 
    5815                 :          0 :   auto_vec <tree, 8> aexprs;
    5816                 :          0 :   auto_vec <hsa_op_reg *, 8> aregs;
    5817                 :            : 
    5818                 :            :   /* Calling split_edge when processing a PHI node messes up with the order of
    5819                 :            :      gimple phi node arguments (it moves the one associated with the edge to
    5820                 :            :      the end).  We need to keep the order of edges and arguments of HSA phi
    5821                 :            :      node arguments consistent, so we do all required splitting as the first
    5822                 :            :      step, and in reverse order as to not be affected by the re-orderings.  */
    5823                 :          0 :   for (unsigned j = count; j != 0; j--)
    5824                 :            :     {
    5825                 :          0 :       unsigned i = j - 1;
    5826                 :          0 :       tree op = gimple_phi_arg_def (phi_stmt, i);
    5827                 :          0 :       if (TREE_CODE (op) != ADDR_EXPR)
    5828                 :          0 :         continue;
    5829                 :            : 
    5830                 :          0 :       edge e = gimple_phi_arg_edge (as_a <gphi *> (phi_stmt), i);
    5831                 :          0 :       hsa_bb *hbb_src = hsa_init_new_bb (split_edge (e));
    5832                 :          0 :       hsa_op_address *addr = gen_hsa_addr (TREE_OPERAND (op, 0),
    5833                 :            :                                            hbb_src);
    5834                 :            : 
    5835                 :          0 :       hsa_op_reg *dest
    5836                 :          0 :         = new hsa_op_reg (hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT));
    5837                 :          0 :       hsa_insn_basic *insn
    5838                 :            :         = new hsa_insn_basic (2, BRIG_OPCODE_LDA, BRIG_TYPE_U64,
    5839                 :          0 :                               dest, addr);
    5840                 :          0 :       hbb_src->append_insn (insn);
    5841                 :          0 :       aexprs.safe_push (op);
    5842                 :          0 :       aregs.safe_push (dest);
    5843                 :            :     }
    5844                 :            : 
    5845                 :          0 :   tree lhs = gimple_phi_result (phi_stmt);
    5846                 :          0 :   for (unsigned i = 0; i < count; i++)
    5847                 :            :     {
    5848                 :          0 :       tree op = gimple_phi_arg_def (phi_stmt, i);
    5849                 :            : 
    5850                 :          0 :       if (TREE_CODE (op) == SSA_NAME)
    5851                 :            :         {
    5852                 :          0 :           hsa_op_reg *hreg = hsa_cfun->reg_for_gimple_ssa (op);
    5853                 :          0 :           hphi->set_op (i, hreg);
    5854                 :            :         }
    5855                 :            :       else
    5856                 :            :         {
    5857                 :          0 :           gcc_assert (is_gimple_min_invariant (op));
    5858                 :          0 :           tree t = TREE_TYPE (op);
    5859                 :          0 :           if (!POINTER_TYPE_P (t)
    5860                 :          0 :               || (TREE_CODE (op) == STRING_CST
    5861                 :          0 :                   && TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE))
    5862                 :          0 :             hphi->set_op (i, new hsa_op_immed (op));
    5863                 :          0 :           else if (POINTER_TYPE_P (TREE_TYPE (lhs))
    5864                 :          0 :                    && TREE_CODE (op) == INTEGER_CST)
    5865                 :            :             {
    5866                 :            :               /* Handle assignment of NULL value to a pointer type.  */
    5867                 :          0 :               hphi->set_op (i, new hsa_op_immed (op));
    5868                 :            :             }
    5869                 :          0 :           else if (TREE_CODE (op) == ADDR_EXPR)
    5870                 :            :             {
    5871                 :          0 :               hsa_op_reg *dest = NULL;
    5872                 :          0 :               for (unsigned a_idx = 0; a_idx < aexprs.length (); a_idx++)
    5873                 :          0 :                 if (aexprs[a_idx] == op)
    5874                 :            :                   {
    5875                 :          0 :                     dest = aregs[a_idx];
    5876                 :          0 :                     break;
    5877                 :            :                   }
    5878                 :          0 :               gcc_assert (dest);
    5879                 :          0 :               hphi->set_op (i, dest);
    5880                 :            :             }
    5881                 :            :           else
    5882                 :            :             {
    5883                 :          0 :               HSA_SORRY_AT (gimple_location (phi_stmt),
    5884                 :            :                             "support for HSA does not handle PHI nodes with "
    5885                 :            :                             "constant address operands");
    5886                 :          0 :               return;
    5887                 :            :             }
    5888                 :            :         }
    5889                 :            :     }
    5890                 :            : 
    5891                 :          0 :   hbb->append_phi (hphi);
    5892                 :            : }
    5893                 :            : 
    5894                 :            : /* Constructor of class containing HSA-specific information about a basic
    5895                 :            :    block.  CFG_BB is the CFG BB this HSA BB is associated with.  IDX is the new
    5896                 :            :    index of this BB (so that the constructor does not attempt to use
    5897                 :            :    hsa_cfun during its construction).  */
    5898                 :            : 
    5899                 :          0 : hsa_bb::hsa_bb (basic_block cfg_bb, int idx)
    5900                 :            :   : m_bb (cfg_bb), m_first_insn (NULL), m_last_insn (NULL), m_first_phi (NULL),
    5901                 :          0 :     m_last_phi (NULL), m_index (idx)
    5902                 :            : {
    5903                 :          0 :   gcc_assert (!cfg_bb->aux);
    5904                 :          0 :   cfg_bb->aux = this;
    5905                 :          0 : }
    5906                 :            : 
    5907                 :            : /* Constructor of class containing HSA-specific information about a basic
    5908                 :            :    block.  CFG_BB is the CFG BB this HSA BB is associated with.  */
    5909                 :            : 
    5910                 :          0 : hsa_bb::hsa_bb (basic_block cfg_bb)
    5911                 :            :   : m_bb (cfg_bb), m_first_insn (NULL), m_last_insn (NULL), m_first_phi (NULL),
    5912                 :          0 :     m_last_phi (NULL), m_index (hsa_cfun->m_hbb_count++)
    5913                 :            : {
    5914                 :          0 :   gcc_assert (!cfg_bb->aux);
    5915                 :          0 :   cfg_bb->aux = this;
    5916                 :          0 : }
    5917                 :            : 
    5918                 :            : /* Create and initialize and return a new hsa_bb structure for a given CFG
    5919                 :            :    basic block BB.  */
    5920                 :            : 
    5921                 :            : hsa_bb *
    5922                 :          0 : hsa_init_new_bb (basic_block bb)
    5923                 :            : {
    5924                 :          0 :   void *m = obstack_alloc (&hsa_obstack, sizeof (hsa_bb));
    5925                 :          0 :   return new (m) hsa_bb (bb);
    5926                 :            : }
    5927                 :            : 
    5928                 :            : /* Initialize OMP in an HSA basic block PROLOGUE.  */
    5929                 :            : 
    5930                 :            : static void
    5931                 :          0 : init_prologue (void)
    5932                 :            : {
    5933                 :          0 :   if (!hsa_cfun->m_kern_p)
    5934                 :            :     return;
    5935                 :            : 
    5936                 :          0 :   hsa_bb *prologue = hsa_bb_for_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun));
    5937                 :            : 
    5938                 :            :   /* Create a magic number that is going to be printed by libgomp.  */
    5939                 :          0 :   unsigned index = hsa_get_number_decl_kernel_mappings ();
    5940                 :            : 
    5941                 :            :   /* Emit store to debug argument.  */
    5942                 :          0 :   if (param_hsa_gen_debug_stores > 0)
    5943                 :          0 :     set_debug_value (prologue, new hsa_op_immed (1000 + index, BRIG_TYPE_U64));
    5944                 :            : }
    5945                 :            : 
    5946                 :            : /* Initialize hsa_num_threads to a default value.  */
    5947                 :            : 
    5948                 :            : static void
    5949                 :          0 : init_hsa_num_threads (void)
    5950                 :            : {
    5951                 :          0 :   hsa_bb *prologue = hsa_bb_for_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun));
    5952                 :            : 
    5953                 :            :   /* Save the default value to private variable hsa_num_threads.  */
    5954                 :          0 :   hsa_insn_basic *basic
    5955                 :          0 :     = new hsa_insn_mem (BRIG_OPCODE_ST, hsa_num_threads->m_type,
    5956                 :          0 :                         new hsa_op_immed (0, hsa_num_threads->m_type),
    5957                 :          0 :                         new hsa_op_address (hsa_num_threads));
    5958                 :          0 :   prologue->append_insn (basic);
    5959                 :          0 : }
    5960                 :            : 
    5961                 :            : /* Go over gimple representation and generate our internal HSA one.  */
    5962                 :            : 
    5963                 :            : static void
    5964                 :          0 : gen_body_from_gimple ()
    5965                 :            : {
    5966                 :          0 :   basic_block bb;
    5967                 :            : 
    5968                 :            :   /* Verify CFG for complex edges we are unable to handle.  */
    5969                 :          0 :   edge_iterator ei;
    5970                 :          0 :   edge e;
    5971                 :            : 
    5972                 :          0 :   FOR_EACH_BB_FN (bb, cfun)
    5973                 :            :     {
    5974                 :          0 :       FOR_EACH_EDGE (e, ei, bb->succs)
    5975                 :            :         {
    5976                 :            :           /* Verify all unsupported flags for edges that point
    5977                 :            :              to the same basic block.  */
    5978                 :          0 :           if (e->flags & EDGE_EH)
    5979                 :            :             {
    5980                 :          0 :               HSA_SORRY_AT (UNKNOWN_LOCATION,
    5981                 :            :                             "support for HSA does not implement exception "
    5982                 :            :                             "handling");
    5983                 :          0 :               return;
    5984                 :            :             }
    5985                 :            :         }
    5986                 :            :     }
    5987                 :            : 
    5988                 :          0 :   FOR_EACH_BB_FN (bb, cfun)
    5989                 :            :     {
    5990                 :          0 :       gimple_stmt_iterator gsi;
    5991                 :          0 :       hsa_bb *hbb = hsa_bb_for_bb (bb);
    5992                 :          0 :       if (hbb)
    5993                 :          0 :         continue;
    5994                 :            : 
    5995                 :          0 :       hbb = hsa_init_new_bb (bb);
    5996                 :            : 
    5997                 :          0 :       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
    5998                 :            :         {
    5999                 :          0 :           gen_hsa_insns_for_gimple_stmt (gsi_stmt (gsi), hbb);
    6000                 :          0 :           if (hsa_seen_error ())
    6001                 :          0 :             return;
    6002                 :            :         }
    6003                 :            :     }
    6004                 :            : 
    6005                 :          0 :   FOR_EACH_BB_FN (bb, cfun)
    6006                 :            :     {
    6007                 :          0 :       gimple_stmt_iterator gsi;
    6008                 :          0 :       hsa_bb *hbb = hsa_bb_for_bb (bb);
    6009                 :          0 :       gcc_assert (hbb != NULL);
    6010                 :            : 
    6011                 :          0 :       for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
    6012                 :          0 :         if (!virtual_operand_p (gimple_phi_result (gsi_stmt (gsi))))
    6013                 :          0 :           gen_hsa_phi_from_gimple_phi (gsi_stmt (gsi), hbb);
    6014                 :            :     }
    6015                 :            : 
    6016                 :          0 :   if (dump_file && (dump_flags & TDF_DETAILS))
    6017                 :            :     {
    6018                 :          0 :       fprintf (dump_file, "------- Generated SSA form -------\n");
    6019                 :          0 :       dump_hsa_cfun (dump_file);
    6020                 :            :     }
    6021                 :            : }
    6022                 :            : 
    6023                 :            : static void
    6024                 :          0 : gen_function_decl_parameters (hsa_function_representation *f,
    6025                 :            :                               tree decl)
    6026                 :            : {
    6027                 :          0 :   tree parm;
    6028                 :          0 :   unsigned i;
    6029                 :            : 
    6030                 :          0 :   for (parm = TYPE_ARG_TYPES (TREE_TYPE (decl)), i = 0;
    6031                 :          0 :        parm;
    6032                 :          0 :        parm = TREE_CHAIN (parm), i++)
    6033                 :            :     {
    6034                 :            :       /* Result type if last in the tree list.  */
    6035                 :          0 :       if (TREE_CHAIN (parm) == NULL)
    6036                 :            :         break;
    6037                 :            : 
    6038                 :          0 :       tree v = TREE_VALUE (parm);
    6039                 :            : 
    6040                 :          0 :       hsa_symbol *arg = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_ARG,
    6041                 :          0 :                                         BRIG_LINKAGE_NONE);
    6042                 :          0 :       arg->m_type = hsa_type_for_tree_type (v, &arg->m_dim);
    6043                 :          0 :       arg->m_name_number = i;
    6044                 :            : 
    6045                 :          0 :       f->m_input_args.safe_push (arg);
    6046                 :            :     }
    6047                 :            : 
    6048                 :          0 :   tree result_type = TREE_TYPE (TREE_TYPE (decl));
    6049                 :          0 :   if (!VOID_TYPE_P (result_type))
    6050                 :            :     {
    6051                 :          0 :       f->m_output_arg = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_ARG,
    6052                 :          0 :                                         BRIG_LINKAGE_NONE);
    6053                 :          0 :       f->m_output_arg->m_type
    6054                 :          0 :         = hsa_type_for_tree_type (result_type, &f->m_output_arg->m_dim);
    6055                 :          0 :       f->m_output_arg->m_name = "res";
    6056                 :            :     }
    6057                 :          0 : }
    6058                 :            : 
    6059                 :            : /* Generate the vector of parameters of the HSA representation of the current
    6060                 :            :    function.  This also includes the output parameter representing the
    6061                 :            :    result.  */
    6062                 :            : 
    6063                 :            : static void
    6064                 :          0 : gen_function_def_parameters ()
    6065                 :            : {
    6066                 :          0 :   tree parm;
    6067                 :            : 
    6068                 :          0 :   hsa_bb *prologue = hsa_bb_for_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun));
    6069                 :            : 
    6070                 :          0 :   for (parm = DECL_ARGUMENTS (cfun->decl); parm;
    6071                 :          0 :        parm = DECL_CHAIN (parm))
    6072                 :            :     {
    6073                 :          0 :       class hsa_symbol **slot;
    6074                 :            : 
    6075                 :          0 :       hsa_symbol *arg
    6076                 :          0 :         = new hsa_symbol (BRIG_TYPE_NONE, hsa_cfun->m_kern_p
    6077                 :            :                           ? BRIG_SEGMENT_KERNARG : BRIG_SEGMENT_ARG,
    6078                 :          0 :                           BRIG_LINKAGE_FUNCTION);
    6079                 :          0 :       arg->fillup_for_decl (parm);
    6080                 :            : 
    6081                 :          0 :       hsa_cfun->m_input_args.safe_push (arg);
    6082                 :            : 
    6083                 :          0 :       if (hsa_seen_error ())
    6084                 :          0 :         return;
    6085                 :            : 
    6086                 :          0 :       arg->m_name = hsa_get_declaration_name (parm);
    6087                 :            : 
    6088                 :            :       /* Copy all input arguments and create corresponding private symbols
    6089                 :            :          for them.  */
    6090                 :          0 :       hsa_symbol *private_arg;
    6091                 :          0 :       hsa_op_address *parm_addr = new hsa_op_address (arg);
    6092                 :            : 
    6093                 :          0 :       if (TREE_ADDRESSABLE (parm)
    6094                 :          0 :           || (!is_gimple_reg (parm) && !TREE_READONLY (parm)))
    6095                 :            :         {
    6096                 :          0 :           private_arg = hsa_cfun->create_hsa_temporary (arg->m_type);
    6097                 :          0 :           private_arg->fillup_for_decl (parm);
    6098                 :            : 
    6099                 :          0 :           BrigAlignment8_t align = MIN (arg->m_align, private_arg->m_align);
    6100                 :            : 
    6101                 :          0 :           hsa_op_address *private_arg_addr = new hsa_op_address (private_arg);
    6102                 :          0 :           gen_hsa_memory_copy (prologue, private_arg_addr, parm_addr,
    6103                 :          0 :                                arg->total_byte_size (), align);
    6104                 :            :         }
    6105                 :            :       else
    6106                 :          0 :         private_arg = arg;
    6107                 :            : 
    6108                 :          0 :       slot = hsa_cfun->m_local_symbols->find_slot (private_arg, INSERT);
    6109                 :          0 :       gcc_assert (!*slot);
    6110                 :          0 :       *slot = private_arg;
    6111                 :            : 
    6112                 :          0 :       if (is_gimple_reg (parm))
    6113                 :            :         {
    6114                 :          0 :           tree ddef = ssa_default_def (cfun, parm);
    6115                 :          0 :           if (ddef && !has_zero_uses (ddef))
    6116                 :            :             {
    6117                 :          0 :               BrigType16_t t = hsa_type_for_scalar_tree_type (TREE_TYPE (ddef),
    6118                 :            :                                                               false);
    6119                 :          0 :               BrigType16_t mtype = mem_type_for_type (t);
    6120                 :          0 :               hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (ddef);
    6121                 :          0 :               hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, mtype,
    6122                 :          0 :                                                     dest, parm_addr);
    6123                 :          0 :               gcc_assert (!parm_addr->m_reg);
    6124                 :          0 :               prologue->append_insn (mem);
    6125                 :            :             }
    6126                 :            :         }
    6127                 :            :     }
    6128                 :            : 
    6129                 :          0 :   if (!VOID_TYPE_P (TREE_TYPE (TREE_TYPE (cfun->decl))))
    6130                 :            :     {
    6131                 :          0 :       class hsa_symbol **slot;
    6132                 :            : 
    6133                 :          0 :       hsa_cfun->m_output_arg = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_ARG,
    6134                 :          0 :                                                BRIG_LINKAGE_FUNCTION);
    6135                 :          0 :       hsa_cfun->m_output_arg->fillup_for_decl (DECL_RESULT (cfun->decl));
    6136                 :            : 
    6137                 :          0 :       if (hsa_seen_error ())
    6138                 :            :         return;
    6139                 :            : 
    6140                 :          0 :       hsa_cfun->m_output_arg->m_name = "res";
    6141                 :          0 :       slot = hsa_cfun->m_local_symbols->find_slot (hsa_cfun->m_output_arg,
    6142                 :            :                                                    INSERT);
    6143                 :          0 :       gcc_assert (!*slot);
    6144                 :          0 :       *slot = hsa_cfun->m_output_arg;
    6145                 :            :     }
    6146                 :            : }
    6147                 :            : 
    6148                 :            : /* Generate function representation that corresponds to
    6149                 :            :    a function declaration.  */
    6150                 :            : 
    6151                 :            : hsa_function_representation *
    6152                 :          0 : hsa_generate_function_declaration (tree decl)
    6153                 :            : {
    6154                 :          0 :   hsa_function_representation *fun
    6155                 :          0 :     = new hsa_function_representation (decl, false, 0);
    6156                 :            : 
    6157                 :          0 :   fun->m_declaration_p = true;
    6158                 :          0 :   fun->m_name = get_brig_function_name (decl);
    6159                 :          0 :   gen_function_decl_parameters (fun, decl);
    6160                 :            : 
    6161                 :          0 :   return fun;
    6162                 :            : }
    6163                 :            : 
    6164                 :            : 
    6165                 :            : /* Generate function representation that corresponds to
    6166                 :            :    an internal FN.  */
    6167                 :            : 
    6168                 :            : hsa_function_representation *
    6169                 :          0 : hsa_generate_internal_fn_decl (hsa_internal_fn *fn)
    6170                 :            : {
    6171                 :          0 :   hsa_function_representation *fun = new hsa_function_representation (fn);
    6172                 :            : 
    6173                 :          0 :   fun->m_name = fn->name ();
    6174                 :            : 
    6175                 :          0 :   for (unsigned i = 0; i < fn->get_arity (); i++)
    6176                 :            :     {
    6177                 :          0 :       hsa_symbol *arg
    6178                 :          0 :         = new hsa_symbol (fn->get_argument_type (i), BRIG_SEGMENT_ARG,
    6179                 :          0 :                           BRIG_LINKAGE_NONE);
    6180                 :          0 :       arg->m_name_number = i;
    6181                 :          0 :       fun->m_input_args.safe_push (arg);
    6182                 :            :     }
    6183                 :            : 
    6184                 :          0 :   fun->m_output_arg = new hsa_symbol (fn->get_argument_type (-1),
    6185                 :          0 :                                       BRIG_SEGMENT_ARG, BRIG_LINKAGE_NONE);
    6186                 :          0 :   fun->m_output_arg->m_name = "res";
    6187                 :            : 
    6188                 :          0 :   return fun;
    6189                 :            : }
    6190                 :            : 
    6191                 :            : /* Return true if switch statement S can be transformed
    6192                 :            :    to a SBR instruction in HSAIL.  */
    6193                 :            : 
    6194                 :            : static bool
    6195                 :          0 : transformable_switch_to_sbr_p (gswitch *s)
    6196                 :            : {
    6197                 :            :   /* Identify if a switch statement can be transformed to
    6198                 :            :      SBR instruction, like:
    6199                 :            : 
    6200                 :            :      sbr_u32 $s1 [@label1, @label2, @label3];
    6201                 :            :   */
    6202                 :            : 
    6203                 :          0 :   tree size = get_switch_size (s);
    6204                 :          0 :   if (!tree_fits_uhwi_p (size))
    6205                 :            :     return false;
    6206                 :            : 
    6207                 :          0 :   if (tree_to_uhwi (size) > HSA_MAXIMUM_SBR_LABELS)
    6208                 :          0 :     return false;
    6209                 :            : 
    6210                 :            :   return true;
    6211                 :            : }
    6212                 :            : 
    6213                 :            : /* Structure hold connection between PHI nodes and immediate
    6214                 :            :    values hold by there nodes.  */
    6215                 :            : 
    6216                 :            : class phi_definition
    6217                 :            : {
    6218                 :            : public:
    6219                 :          0 :   phi_definition (unsigned phi_i, unsigned label_i, tree imm):
    6220                 :          0 :     phi_index (phi_i), label_index (label_i), phi_value (imm)
    6221                 :            :   {}
    6222                 :            : 
    6223                 :            :   unsigned phi_index;
    6224                 :            :   unsigned label_index;
    6225                 :            :   tree phi_value;
    6226                 :            : };
    6227                 :            : 
    6228                 :            : /* Sum slice of a vector V, starting from index START and ending
    6229                 :            :    at the index END - 1.  */
    6230                 :            : 
    6231                 :            : template <typename T>
    6232                 :            : static
    6233                 :          0 : T sum_slice (const auto_vec <T> &v, unsigned start, unsigned end,
    6234                 :            :              T zero)
    6235                 :            : {
    6236                 :          0 :   T s = zero;
    6237                 :            : 
    6238                 :          0 :   for (unsigned i = start; i < end; i++)
    6239                 :          0 :     s += v[i];
    6240                 :            : 
    6241                 :          0 :   return s;
    6242                 :            : }
    6243                 :            : 
    6244                 :            : /* Function transforms GIMPLE SWITCH statements to a series of IF statements.
    6245                 :            :    Let's assume following example:
    6246                 :            : 
    6247                 :            : L0:
    6248                 :            :    switch (index)
    6249                 :            :      case C1:
    6250                 :            : L1:    hard_work_1 ();
    6251                 :            :        break;
    6252                 :            :      case C2..C3:
    6253                 :            : L2:    hard_work_2 ();
    6254                 :            :        break;
    6255                 :            :      default:
    6256                 :            : LD:    hard_work_3 ();
    6257                 :            :        break;
    6258                 :            : 
    6259                 :            :   The transformation encompasses following steps:
    6260                 :            :     1) all immediate values used by edges coming from the switch basic block
    6261                 :            :        are saved
    6262                 :            :     2) all these edges are removed
    6263                 :            :     3) the switch statement (in L0) is replaced by:
    6264                 :            :          if (index == C1)
    6265                 :            :            goto L1;
    6266                 :            :          else
    6267                 :            :            goto L1';
    6268                 :            : 
    6269                 :            :     4) newly created basic block Lx' is used for generation of
    6270                 :            :        a next condition
    6271                 :            :     5) else branch of the last condition goes to LD
    6272                 :            :     6) fix all immediate values in PHI nodes that were propagated though
    6273                 :            :        edges that were removed in step 2
    6274                 :            : 
    6275                 :            :   Note: if a case is made by a range C1..C2, then process
    6276                 :            :         following transformation:
    6277                 :            : 
    6278                 :            :   switch_cond_op1 = C1 <= index;
    6279                 :            :   switch_cond_op2 = index <= C2;
    6280                 :            :   switch_cond_and = switch_cond_op1 & switch_cond_op2;
    6281                 :            :   if (switch_cond_and != 0)
    6282                 :            :     goto Lx;
    6283                 :            :   else
    6284                 :            :     goto Ly;
    6285                 :            : 
    6286                 :            : */
    6287                 :            : 
    6288                 :            : static bool
    6289                 :          0 : convert_switch_statements (void)
    6290                 :            : {
    6291                 :          0 :   basic_block bb;
    6292                 :            : 
    6293                 :          0 :   bool modified_cfg = false;
    6294                 :            : 
    6295                 :          0 :   FOR_EACH_BB_FN (bb, cfun)
    6296                 :            :   {
    6297                 :          0 :     gimple_stmt_iterator gsi = gsi_last_bb (bb);
    6298                 :          0 :     if (gsi_end_p (gsi))
    6299                 :          0 :       continue;
    6300                 :            : 
    6301                 :          0 :     gimple *stmt = gsi_stmt (gsi);
    6302                 :            : 
    6303                 :          0 :     if (gimple_code (stmt) == GIMPLE_SWITCH)
    6304                 :            :       {
    6305                 :          0 :         gswitch *s = as_a <gswitch *> (stmt);
    6306                 :            : 
    6307                 :            :         /* If the switch can utilize SBR insn, skip the statement.  */
    6308                 :          0 :         if (transformable_switch_to_sbr_p (s))
    6309                 :          0 :           continue;
    6310                 :            : 
    6311                 :          0 :         modified_cfg = true;
    6312                 :            : 
    6313                 :          0 :         unsigned labels = gimple_switch_num_labels (s);
    6314                 :          0 :         tree index = gimple_switch_index (s);
    6315                 :          0 :         tree index_type = TREE_TYPE (index);
    6316                 :          0 :         tree default_label = gimple_switch_default_label (s);
    6317                 :          0 :         basic_block default_label_bb
    6318                 :          0 :           = label_to_block (cfun, CASE_LABEL (default_label));
    6319                 :          0 :         basic_block cur_bb = bb;
    6320                 :            : 
    6321                 :          0 :         auto_vec <edge> new_edges;
    6322                 :          0 :         auto_vec <phi_definition *> phi_todo_list;
    6323                 :          0 :         auto_vec <profile_count> edge_counts;
    6324                 :          0 :         auto_vec <profile_probability> edge_probabilities;
    6325                 :            : 
    6326                 :            :         /* Investigate all labels that and PHI nodes in these edges which
    6327                 :            :            should be fixed after we add new collection of edges.  */
    6328                 :          0 :         for (unsigned i = 0; i < labels; i++)
    6329                 :            :           {
    6330                 :          0 :             basic_block label_bb = gimple_switch_label_bb (cfun, s, i);
    6331                 :          0 :             edge e = find_edge (bb, label_bb);
    6332                 :          0 :             edge_counts.safe_push (e->count ());
    6333                 :          0 :             edge_probabilities.safe_push (e->probability);
    6334                 :          0 :             gphi_iterator phi_gsi;
    6335                 :            : 
    6336                 :            :             /* Save PHI definitions that will be destroyed because of an edge
    6337                 :            :                is going to be removed.  */
    6338                 :          0 :             unsigned phi_index = 0;
    6339                 :          0 :             for (phi_gsi = gsi_start_phis (e->dest);
    6340                 :          0 :                  !gsi_end_p (phi_gsi); gsi_next (&phi_gsi))
    6341                 :            :               {
    6342                 :          0 :                 gphi *phi = phi_gsi.phi ();
    6343                 :          0 :                 for (unsigned j = 0; j < gimple_phi_num_args (phi); j++)
    6344                 :            :                   {
    6345                 :          0 :                     if (gimple_phi_arg_edge (phi, j) == e)
    6346                 :            :                       {
    6347                 :          0 :                         tree imm = gimple_phi_arg_def (phi, j);
    6348                 :          0 :                         phi_definition *p = new phi_definition (phi_index, i,
    6349                 :          0 :                                                                 imm);
    6350                 :          0 :                         phi_todo_list.safe_push (p);
    6351                 :          0 :                         break;
    6352                 :            :                       }
    6353                 :            :                   }
    6354                 :          0 :                 phi_index++;
    6355                 :            :               }
    6356                 :            :           }
    6357                 :            : 
    6358                 :            :         /* Remove all edges for the current basic block.  */
    6359                 :          0 :         for (int i = EDGE_COUNT (bb->succs) - 1; i >= 0; i--)
    6360                 :            :           {
    6361                 :          0 :             edge e = EDGE_SUCC (bb, i);
    6362                 :          0 :             remove_edge (e);
    6363                 :            :           }
    6364                 :            : 
    6365                 :            :         /* Iterate all non-default labels.  */
    6366                 :          0 :         for (unsigned i = 1; i < labels; i++)
    6367                 :            :           {
    6368                 :          0 :             tree label = gimple_switch_label (s, i);
    6369                 :          0 :             tree low = CASE_LOW (label);
    6370                 :          0 :             tree high = CASE_HIGH (label);
    6371                 :            : 
    6372                 :          0 :             if (!useless_type_conversion_p (TREE_TYPE (low), index_type))
    6373                 :          0 :               low = fold_convert (index_type, low);
    6374                 :            : 
    6375                 :          0 :             gimple_stmt_iterator cond_gsi = gsi_last_bb (cur_bb);
    6376                 :          0 :             gimple *c = NULL;
    6377                 :          0 :             if (high)
    6378                 :            :               {
    6379                 :          0 :                 tree tmp1 = make_temp_ssa_name (boolean_type_node, NULL,
    6380                 :            :                                                 "switch_cond_op1");
    6381                 :            : 
    6382                 :          0 :                 gimple *assign1 = gimple_build_assign (tmp1, LE_EXPR, low,
    6383                 :            :                                                       index);
    6384                 :            : 
    6385                 :          0 :                 tree tmp2 = make_temp_ssa_name (boolean_type_node, NULL,
    6386                 :            :                                                 "switch_cond_op2");
    6387                 :            : 
    6388                 :          0 :                 if (!useless_type_conversion_p (TREE_TYPE (high), index_type))
    6389                 :          0 :                   high = fold_convert (index_type, high);
    6390                 :          0 :                 gimple *assign2 = gimple_build_assign (tmp2, LE_EXPR, index,
    6391                 :            :                                                       high);
    6392                 :            : 
    6393                 :          0 :                 tree tmp3 = make_temp_ssa_name (boolean_type_node, NULL,
    6394                 :            :                                                 "switch_cond_and");
    6395                 :          0 :                 gimple *assign3 = gimple_build_assign (tmp3, BIT_AND_EXPR, tmp1,
    6396                 :            :                                                       tmp2);
    6397                 :            : 
    6398                 :          0 :                 gsi_insert_before (&cond_gsi, assign1, GSI_SAME_STMT);
    6399                 :          0 :                 gsi_insert_before (&cond_gsi, assign2, GSI_SAME_STMT);
    6400                 :          0 :                 gsi_insert_before (&cond_gsi, assign3, GSI_SAME_STMT);
    6401                 :            : 
    6402                 :          0 :                 tree b = constant_boolean_node (false, boolean_type_node);
    6403                 :          0 :                 c = gimple_build_cond (NE_EXPR, tmp3, b, NULL, NULL);
    6404                 :            :               }
    6405                 :            :             else
    6406                 :          0 :               c = gimple_build_cond (EQ_EXPR, index, low, NULL, NULL);
    6407                 :            : 
    6408                 :          0 :             gimple_set_location (c, gimple_location (stmt));
    6409                 :            : 
    6410                 :          0 :             gsi_insert_before (&cond_gsi, c, GSI_SAME_STMT);
    6411                 :            : 
    6412                 :          0 :             basic_block label_bb = label_to_block (cfun, CASE_LABEL (label));
    6413                 :          0 :             edge new_edge = make_edge (cur_bb, label_bb, EDGE_TRUE_VALUE);
    6414                 :          0 :             profile_probability prob_sum = sum_slice <profile_probability>
    6415                 :          0 :                  (edge_probabilities, i, labels, profile_probability::never ())
    6416                 :          0 :                   + edge_probabilities[0];
    6417                 :            : 
    6418                 :          0 :             if (prob_sum.initialized_p ())
    6419                 :          0 :               new_edge->probability = edge_probabilities[i] / prob_sum;
    6420                 :            : 
    6421                 :          0 :             new_edges.safe_push (new_edge);
    6422                 :            : 
    6423                 :          0 :             if (i < labels - 1)
    6424                 :            :               {
    6425                 :            :                 /* Prepare another basic block that will contain
    6426                 :            :                    next condition.  */
    6427                 :          0 :                 basic_block next_bb = create_empty_bb (cur_bb);
    6428                 :          0 :                 if (current_loops)
    6429                 :            :                   {
    6430                 :          0 :                     add_bb_to_loop (next_bb, cur_bb->loop_father);
    6431                 :          0 :                     loops_state_set (LOOPS_NEED_FIXUP);
    6432                 :            :                   }
    6433                 :            : 
    6434                 :          0 :                 edge next_edge = make_edge (cur_bb, next_bb, EDGE_FALSE_VALUE);
    6435                 :          0 :                 next_edge->probability = new_edge->probability.invert ();
    6436                 :          0 :                 next_bb->count = next_edge->count ();
    6437                 :          0 :                 cur_bb = next_bb;
    6438                 :            :               }
    6439                 :            :             else /* Link last IF statement and default label
    6440                 :            :                     of the switch.  */
    6441                 :            :               {
    6442                 :          0 :                 edge e = make_edge (cur_bb, default_label_bb, EDGE_FALSE_VALUE);
    6443                 :          0 :                 e->probability = new_edge->probability.invert ();
    6444                 :          0 :                 new_edges.safe_insert (0, e);
    6445                 :            :               }
    6446                 :            :           }
    6447                 :            : 
    6448                 :            :           /* Restore original PHI immediate value.  */
    6449                 :          0 :           for (unsigned i = 0; i < phi_todo_list.length (); i++)
    6450                 :            :             {
    6451                 :          0 :               phi_definition *phi_def = phi_todo_list[i];
    6452                 :          0 :               edge new_edge = new_edges[phi_def->label_index];
    6453                 :            : 
    6454                 :          0 :               gphi_iterator it = gsi_start_phis (new_edge->dest);
    6455                 :          0 :               for (unsigned i = 0; i < phi_def->phi_index; i++)
    6456                 :          0 :                 gsi_next (&it);
    6457                 :            : 
    6458                 :          0 :               gphi *phi = it.phi ();
    6459                 :          0 :               add_phi_arg (phi, phi_def->phi_value, new_edge, UNKNOWN_LOCATION);
    6460                 :          0 :               delete phi_def;
    6461                 :            :             }
    6462                 :            : 
    6463                 :            :         /* Remove the original GIMPLE switch statement.  */
    6464                 :          0 :         gsi_remove (&gsi, true);
    6465                 :            :       }
    6466                 :            :   }
    6467                 :            : 
    6468                 :          0 :   if (dump_file)
    6469                 :          0 :     dump_function_to_file (current_function_decl, dump_file, TDF_DETAILS);
    6470                 :            : 
    6471                 :          0 :   return modified_cfg;
    6472                 :            : }
    6473                 :            : 
    6474                 :            : /* Expand builtins that can't be handled by HSA back-end.  */
    6475                 :            : 
    6476                 :            : static void
    6477                 :          0 : expand_builtins ()
    6478                 :            : {
    6479                 :          0 :   basic_block bb;
    6480                 :            : 
    6481                 :          0 :   FOR_EACH_BB_FN (bb, cfun)
    6482                 :            :   {
    6483                 :          0 :     for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
    6484                 :          0 :          gsi_next (&gsi))
    6485                 :            :       {
    6486                 :          0 :         gimple *stmt = gsi_stmt (gsi);
    6487                 :            : 
    6488                 :          0 :         if (gimple_code (stmt) != GIMPLE_CALL)
    6489                 :          0 :           continue;
    6490                 :            : 
    6491                 :          0 :         gcall *call = as_a <gcall *> (stmt);
    6492                 :            : 
    6493                 :          0 :         if (!gimple_call_builtin_p (call, BUILT_IN_NORMAL))
    6494                 :          0 :           continue;
    6495                 :            : 
    6496                 :          0 :         tree fndecl = gimple_call_fndecl (stmt);
    6497                 :          0 :         enum built_in_function fn = DECL_FUNCTION_CODE (fndecl);
    6498                 :          0 :         switch (fn)
    6499                 :            :           {
    6500                 :          0 :           case BUILT_IN_CEXPF:
    6501                 :          0 :           case BUILT_IN_CEXPIF:
    6502                 :          0 :           case BUILT_IN_CEXPI:
    6503                 :          0 :             {
    6504                 :            :               /* Similar to builtins.c (expand_builtin_cexpi), the builtin
    6505                 :            :                  can be transformed to: cexp(I * z) = ccos(z) + I * csin(z).  */
    6506                 :          0 :               tree lhs = gimple_call_lhs (stmt);
    6507                 :          0 :               tree rhs = gimple_call_arg (stmt, 0);
    6508                 :          0 :               tree rhs_type = TREE_TYPE (rhs);
    6509                 :          0 :               bool float_type_p = rhs_type == float_type_node;
    6510                 :          0 :               tree real_part = make_temp_ssa_name (rhs_type, NULL,
    6511                 :            :                                                    "cexp_real_part");
    6512                 :          0 :               tree imag_part = make_temp_ssa_name (rhs_type, NULL,
    6513                 :            :                                                    "cexp_imag_part");
    6514                 :            : 
    6515                 :          0 :               tree cos_fndecl
    6516                 :          0 :                 = mathfn_built_in (rhs_type, fn == float_type_p
    6517                 :            :                                    ? BUILT_IN_COSF : BUILT_IN_COS);
    6518                 :          0 :               gcall *cos = gimple_build_call (cos_fndecl, 1, rhs);
    6519                 :          0 :               gimple_call_set_lhs (cos, real_part);
    6520                 :          0 :               gsi_insert_before (&gsi, cos, GSI_SAME_STMT);
    6521                 :            : 
    6522                 :          0 :               tree sin_fndecl
    6523                 :          0 :                 = mathfn_built_in (rhs_type, fn == float_type_p
    6524                 :            :                                    ? BUILT_IN_SINF : BUILT_IN_SIN);
    6525                 :          0 :               gcall *sin = gimple_build_call (sin_fndecl, 1, rhs);
    6526                 :          0 :               gimple_call_set_lhs (sin, imag_part);
    6527                 :          0 :               gsi_insert_before (&gsi, sin, GSI_SAME_STMT);
    6528                 :            : 
    6529                 :            : 
    6530                 :          0 :               gassign *assign = gimple_build_assign (lhs, COMPLEX_EXPR,
    6531                 :            :                                                      real_part, imag_part);
    6532                 :          0 :               gsi_insert_before (&gsi, assign, GSI_SAME_STMT);
    6533                 :          0 :               gsi_remove (&gsi, true);
    6534                 :            : 
    6535                 :          0 :               break;
    6536                 :            :             }
    6537                 :            :           default:
    6538                 :            :             break;
    6539                 :            :           }
    6540                 :            :       }
    6541                 :            :   }
    6542                 :          0 : }
    6543                 :            : 
    6544                 :            : /* Emit HSA module variables that are global for the entire module.  */
    6545                 :            : 
    6546                 :            : static void
    6547                 :          0 : emit_hsa_module_variables (void)
    6548                 :            : {
    6549                 :          0 :   hsa_num_threads = new hsa_symbol (BRIG_TYPE_U32, BRIG_SEGMENT_PRIVATE,
    6550                 :          0 :                                     BRIG_LINKAGE_MODULE, true);
    6551                 :            : 
    6552                 :          0 :   hsa_num_threads->m_name = "hsa_num_threads";
    6553                 :            : 
    6554                 :          0 :   hsa_brig_emit_omp_symbols ();
    6555                 :          0 : }
    6556                 :            : 
    6557                 :            : /* Generate HSAIL representation of the current function and write into a
    6558                 :            :    special section of the output file.  If KERNEL is set, the function will be
    6559                 :            :    considered an HSA kernel callable from the host, otherwise it will be
    6560                 :            :    compiled as an HSA function callable from other HSA code.  */
    6561                 :            : 
    6562                 :            : static void
    6563                 :          0 : generate_hsa (bool kernel)
    6564                 :            : {
    6565                 :          0 :   hsa_init_data_for_cfun ();
    6566                 :            : 
    6567                 :          0 :   if (hsa_num_threads == NULL)
    6568                 :          0 :     emit_hsa_module_variables ();
    6569                 :            : 
    6570                 :          0 :   bool modified_cfg = convert_switch_statements ();
    6571                 :            :   /* Initialize hsa_cfun.  */
    6572                 :          0 :   hsa_cfun = new hsa_function_representation (cfun->decl, kernel,
    6573                 :          0 :                                               SSANAMES (cfun)->length (),
    6574                 :          0 :                                               modified_cfg);
    6575                 :          0 :   hsa_cfun->init_extra_bbs ();
    6576                 :            : 
    6577                 :          0 :   if (flag_tm)
    6578                 :            :     {
    6579                 :          0 :       HSA_SORRY_AT (UNKNOWN_LOCATION,
    6580                 :            :                     "support for HSA does not implement transactional memory");
    6581                 :          0 :       goto fail;
    6582                 :            :     }
    6583                 :            : 
    6584                 :          0 :   verify_function_arguments (cfun->decl);
    6585                 :          0 :   if (hsa_seen_error ())
    6586                 :          0 :     goto fail;
    6587                 :            : 
    6588                 :          0 :   hsa_cfun->m_name = get_brig_function_name (cfun->decl);
    6589                 :            : 
    6590                 :          0 :   gen_function_def_parameters ();
    6591                 :          0 :   if (hsa_seen_error ())
    6592                 :          0 :     goto fail;
    6593                 :            : 
    6594                 :          0 :   init_prologue ();
    6595                 :            : 
    6596                 :          0 :   gen_body_from_gimple ();
    6597                 :          0 :   if (hsa_seen_error ())
    6598                 :          0 :     goto fail;
    6599                 :            : 
    6600                 :          0 :   if (hsa_cfun->m_kernel_dispatch_count)
    6601                 :          0 :     init_hsa_num_threads ();
    6602                 :            : 
    6603                 :          0 :   if (hsa_cfun->m_kern_p)
    6604                 :            :     {
    6605                 :          0 :       hsa_function_summary *s
    6606                 :          0 :         = hsa_summaries->get_create (cgraph_node::get (hsa_cfun->m_decl));
    6607                 :          0 :       hsa_add_kern_decl_mapping (current_function_decl, hsa_cfun->m_name,
    6608                 :            :                                  hsa_cfun->m_maximum_omp_data_size,
    6609                 :          0 :                                  s->m_gridified_kernel_p);
    6610                 :            :     }
    6611                 :            : 
    6612                 :          0 :   if (flag_checking)
    6613                 :            :     {
    6614                 :          0 :       for (unsigned i = 0; i < hsa_cfun->m_ssa_map.length (); i++)
    6615                 :          0 :         if (hsa_cfun->m_ssa_map[i])
    6616                 :          0 :           hsa_cfun->m_ssa_map[i]->verify_ssa ();
    6617                 :            : 
    6618                 :          0 :       basic_block bb;
    6619                 :          0 :       FOR_EACH_BB_FN (bb, cfun)
    6620                 :            :         {
    6621                 :          0 :           hsa_bb *hbb = hsa_bb_for_bb (bb);
    6622                 :            : 
    6623                 :          0 :           for (hsa_insn_basic *insn = hbb->m_first_insn; insn;
    6624                 :          0 :                insn = insn->m_next)
    6625                 :          0 :             insn->verify ();
    6626                 :            :         }
    6627                 :            :     }
    6628                 :            : 
    6629                 :          0 :   hsa_regalloc ();
    6630                 :          0 :   hsa_brig_emit_function ();
    6631                 :            : 
    6632                 :          0 :  fail:
    6633                 :          0 :   hsa_deinit_data_for_cfun ();
    6634                 :          0 : }
    6635                 :            : 
    6636                 :            : namespace {
    6637                 :            : 
    6638                 :            : const pass_data pass_data_gen_hsail =
    6639                 :            : {
    6640                 :            :   GIMPLE_PASS,
    6641                 :            :   "hsagen",                           /* name */
    6642                 :            :   OPTGROUP_OMP,                         /* optinfo_flags */
    6643                 :            :   TV_NONE,                              /* tv_id */
    6644                 :            :   PROP_cfg | PROP_ssa,                  /* properties_required */
    6645                 :            :   0,                                    /* properties_provided */
    6646                 :            :   0,                                    /* properties_destroyed */
    6647                 :            :   0,                                    /* todo_flags_start */
    6648                 :            :   0                                     /* todo_flags_finish */
    6649                 :            : };
    6650                 :            : 
    6651                 :            : class pass_gen_hsail : public gimple_opt_pass
    6652                 :            : {
    6653                 :            : public:
    6654                 :     200540 :   pass_gen_hsail (gcc::context *ctxt)
    6655                 :     401080 :     : gimple_opt_pass(pass_data_gen_hsail, ctxt)
    6656                 :            :   {}
    6657                 :            : 
    6658                 :            :   /* opt_pass methods: */
    6659                 :            :   bool gate (function *);
    6660                 :            :   unsigned int execute (function *);
    6661                 :            : 
    6662                 :            : }; // class pass_gen_hsail
    6663                 :            : 
    6664                 :            : /* Determine whether or not to run generation of HSAIL.  */
    6665                 :            : 
    6666                 :            : bool
    6667                 :     943374 : pass_gen_hsail::gate (function *f)
    6668                 :            : {
    6669                 :     943374 :   return hsa_gen_requested_p ()
    6670                 :     943374 :     && hsa_gpu_implementation_p (f->decl);
    6671                 :            : }
    6672                 :            : 
    6673                 :            : unsigned int
    6674                 :          0 : pass_gen_hsail::execute (function *)
    6675                 :            : {
    6676                 :          0 :   cgraph_node *node = cgraph_node::get_create (current_function_decl);
    6677                 :          0 :   hsa_function_summary *s = hsa_summaries->get_create (node);
    6678                 :            : 
    6679                 :          0 :   expand_builtins ();
    6680                 :          0 :   generate_hsa (s->m_kind == HSA_KERNEL);
    6681                 :          0 :   TREE_ASM_WRITTEN (current_function_decl) = 1;
    6682                 :          0 :   return TODO_discard_function;
    6683                 :            : }
    6684                 :            : 
    6685                 :            : } // anon namespace
    6686                 :            : 
    6687                 :            : /* Create the instance of hsa gen pass.  */
    6688                 :            : 
    6689                 :            : gimple_opt_pass *
    6690                 :     200540 : make_pass_gen_hsail (gcc::context *ctxt)
    6691                 :            : {
    6692                 :     200540 :   return new pass_gen_hsail (ctxt);
    6693                 :            : }

Generated by: LCOV version 1.0

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto --enable-host-shared. GCC test suite is run with the built compiler.