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