xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/hsa-gen.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
1 /* A pass for lowering gimple to HSAIL
2    Copyright (C) 2013-2020 Free Software Foundation, Inc.
3    Contributed by Martin Jambor <mjambor@suse.cz> and
4    Martin Liska <mliska@suse.cz>.
5 
6 This file is part of GCC.
7 
8 GCC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
12 
13 GCC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3.  If not see
20 <http://www.gnu.org/licenses/>.  */
21 
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "memmodel.h"
26 #include "tm.h"
27 #include "is-a.h"
28 #include "hash-table.h"
29 #include "vec.h"
30 #include "tree.h"
31 #include "tree-pass.h"
32 #include "function.h"
33 #include "basic-block.h"
34 #include "cfg.h"
35 #include "fold-const.h"
36 #include "gimple.h"
37 #include "gimple-iterator.h"
38 #include "bitmap.h"
39 #include "dumpfile.h"
40 #include "gimple-pretty-print.h"
41 #include "diagnostic-core.h"
42 #include "gimple-ssa.h"
43 #include "tree-phinodes.h"
44 #include "stringpool.h"
45 #include "tree-vrp.h"
46 #include "tree-ssanames.h"
47 #include "tree-dfa.h"
48 #include "ssa-iterators.h"
49 #include "cgraph.h"
50 #include "print-tree.h"
51 #include "alloc-pool.h"
52 #include "symbol-summary.h"
53 #include "hsa-common.h"
54 #include "cfghooks.h"
55 #include "tree-cfg.h"
56 #include "cfgloop.h"
57 #include "cfganal.h"
58 #include "builtins.h"
59 #include "gomp-constants.h"
60 #include "internal-fn.h"
61 #include "builtins.h"
62 #include "stor-layout.h"
63 #include "stringpool.h"
64 #include "attribs.h"
65 
66 /* Print a warning message and set that we have seen an error.  */
67 
68 #define HSA_SORRY_ATV(location, message, ...) \
69   do \
70   { \
71     hsa_fail_cfun (); \
72     auto_diagnostic_group d; \
73     if (warning_at (EXPR_LOCATION (hsa_cfun->m_decl), OPT_Whsa, \
74 		    HSA_SORRY_MSG)) \
75       inform (location, message, __VA_ARGS__); \
76   } \
77   while (false)
78 
79 /* Same as previous, but highlight a location.  */
80 
81 #define HSA_SORRY_AT(location, message) \
82   do \
83   { \
84     hsa_fail_cfun (); \
85     auto_diagnostic_group d; \
86     if (warning_at (EXPR_LOCATION (hsa_cfun->m_decl), OPT_Whsa, \
87 		    HSA_SORRY_MSG)) \
88       inform (location, message); \
89   } \
90   while (false)
91 
92 /* Default number of threads used by kernel dispatch.  */
93 
94 #define HSA_DEFAULT_NUM_THREADS 64
95 
96 /* Following structures are defined in the final version
97    of HSA specification.  */
98 
99 /* HSA queue packet is shadow structure, originally provided by AMD.  */
100 
101 struct hsa_queue_packet
102 {
103   uint16_t header;
104   uint16_t setup;
105   uint16_t workgroup_size_x;
106   uint16_t workgroup_size_y;
107   uint16_t workgroup_size_z;
108   uint16_t reserved0;
109   uint32_t grid_size_x;
110   uint32_t grid_size_y;
111   uint32_t grid_size_z;
112   uint32_t private_segment_size;
113   uint32_t group_segment_size;
114   uint64_t kernel_object;
115   void *kernarg_address;
116   uint64_t reserved2;
117   uint64_t completion_signal;
118 };
119 
120 /* HSA queue is shadow structure, originally provided by AMD.  */
121 
122 struct hsa_queue
123 {
124   int type;
125   uint32_t features;
126   void *base_address;
127   uint64_t doorbell_signal;
128   uint32_t size;
129   uint32_t reserved1;
130   uint64_t id;
131 };
132 
133 static struct obstack hsa_obstack;
134 
135 /* List of pointers to all instructions that come from an object allocator.  */
136 static vec <hsa_insn_basic *> hsa_instructions;
137 
138 /* List of pointers to all operands that come from an object allocator.  */
139 static vec <hsa_op_base *> hsa_operands;
140 
hsa_symbol()141 hsa_symbol::hsa_symbol ()
142   : m_decl (NULL_TREE), m_name (NULL), m_name_number (0),
143     m_directive_offset (0), m_type (BRIG_TYPE_NONE),
144     m_segment (BRIG_SEGMENT_NONE), m_linkage (BRIG_LINKAGE_NONE), m_dim (0),
145     m_cst_value (NULL), m_global_scope_p (false), m_seen_error (false),
146     m_allocation (BRIG_ALLOCATION_AUTOMATIC), m_emitted_to_brig (false)
147 {
148 }
149 
150 
hsa_symbol(BrigType16_t type,BrigSegment8_t segment,BrigLinkage8_t linkage,bool global_scope_p,BrigAllocation allocation,BrigAlignment8_t align)151 hsa_symbol::hsa_symbol (BrigType16_t type, BrigSegment8_t segment,
152 			BrigLinkage8_t linkage, bool global_scope_p,
153 			BrigAllocation allocation, BrigAlignment8_t align)
154   : m_decl (NULL_TREE), m_name (NULL), m_name_number (0),
155     m_directive_offset (0), m_type (type), m_segment (segment),
156     m_linkage (linkage), m_dim (0), m_cst_value (NULL),
157     m_global_scope_p (global_scope_p), m_seen_error (false),
158     m_allocation (allocation), m_emitted_to_brig (false), m_align (align)
159 {
160 }
161 
162 unsigned HOST_WIDE_INT
total_byte_size()163 hsa_symbol::total_byte_size ()
164 {
165   unsigned HOST_WIDE_INT s
166     = hsa_type_bit_size (~BRIG_TYPE_ARRAY_MASK & m_type);
167   gcc_assert (s % BITS_PER_UNIT == 0);
168   s /= BITS_PER_UNIT;
169 
170   if (m_dim)
171     s *= m_dim;
172 
173   return s;
174 }
175 
176 /* Forward declaration.  */
177 
178 static BrigType16_t
179 hsa_type_for_tree_type (const_tree type, unsigned HOST_WIDE_INT *dim_p,
180 			bool min32int);
181 
182 void
fillup_for_decl(tree decl)183 hsa_symbol::fillup_for_decl (tree decl)
184 {
185   m_decl = decl;
186   m_type = hsa_type_for_tree_type (TREE_TYPE (decl), &m_dim, false);
187   if (hsa_seen_error ())
188     {
189       m_seen_error = true;
190       return;
191     }
192 
193   m_align = MAX (m_align, hsa_natural_alignment (m_type));
194 }
195 
196 /* Constructor of class representing global HSA function/kernel information and
197    state.  FNDECL is function declaration, KERNEL_P is true if the function
198    is going to become a HSA kernel.  If the function has body, SSA_NAMES_COUNT
199    should be set to number of SSA names used in the function.
200    MODIFIED_CFG is set to true in case we modified control-flow graph
201    of the function.  */
202 
hsa_function_representation(tree fdecl,bool kernel_p,unsigned ssa_names_count,bool modified_cfg)203 hsa_function_representation::hsa_function_representation
204   (tree fdecl, bool kernel_p, unsigned ssa_names_count, bool modified_cfg)
205   : m_name (NULL),
206     m_reg_count (0), m_input_args (vNULL),
207     m_output_arg (NULL), m_spill_symbols (vNULL), m_global_symbols (vNULL),
208     m_private_variables (vNULL), m_called_functions (vNULL),
209     m_called_internal_fns (vNULL), m_hbb_count (0),
210     m_in_ssa (true), m_kern_p (kernel_p), m_declaration_p (false),
211     m_decl (fdecl), m_internal_fn (NULL), m_shadow_reg (NULL),
212     m_kernel_dispatch_count (0), m_maximum_omp_data_size (0),
213     m_seen_error (false), m_temp_symbol_count (0), m_ssa_map (),
214     m_modified_cfg (modified_cfg)
215 {
216   int sym_init_len = (vec_safe_length (cfun->local_decls) / 2) + 1;
217   m_local_symbols = new hash_table <hsa_noop_symbol_hasher> (sym_init_len);
218   m_ssa_map.safe_grow_cleared (ssa_names_count);
219 }
220 
221 /* Constructor of class representing HSA function information that
222    is derived for an internal function.  */
hsa_function_representation(hsa_internal_fn * fn)223 hsa_function_representation::hsa_function_representation (hsa_internal_fn *fn)
224   : m_reg_count (0), m_input_args (vNULL),
225     m_output_arg (NULL), m_local_symbols (NULL),
226     m_spill_symbols (vNULL), m_global_symbols (vNULL),
227     m_private_variables (vNULL), m_called_functions (vNULL),
228     m_called_internal_fns (vNULL), m_hbb_count (0),
229     m_in_ssa (true), m_kern_p (false), m_declaration_p (true), m_decl (NULL),
230     m_internal_fn (fn), m_shadow_reg (NULL), m_kernel_dispatch_count (0),
231     m_maximum_omp_data_size (0), m_seen_error (false), m_temp_symbol_count (0),
232     m_ssa_map () {}
233 
234 /* Destructor of class holding function/kernel-wide information and state.  */
235 
~hsa_function_representation()236 hsa_function_representation::~hsa_function_representation ()
237 {
238   /* Kernel names are deallocated at the end of BRIG output when deallocating
239      hsa_decl_kernel_mapping.  */
240   if (!m_kern_p || m_seen_error)
241     free (m_name);
242 
243   for (unsigned i = 0; i < m_input_args.length (); i++)
244     delete m_input_args[i];
245   m_input_args.release ();
246 
247   delete m_output_arg;
248   delete m_local_symbols;
249 
250   for (unsigned i = 0; i < m_spill_symbols.length (); i++)
251     delete m_spill_symbols[i];
252   m_spill_symbols.release ();
253 
254   hsa_symbol *sym;
255   for (unsigned i = 0; i < m_global_symbols.iterate (i, &sym); i++)
256     if (sym->m_linkage != BRIG_ALLOCATION_PROGRAM)
257       delete sym;
258   m_global_symbols.release ();
259 
260   for (unsigned i = 0; i < m_private_variables.length (); i++)
261     delete m_private_variables[i];
262   m_private_variables.release ();
263   m_called_functions.release ();
264   m_ssa_map.release ();
265 
266   for (unsigned i = 0; i < m_called_internal_fns.length (); i++)
267     delete m_called_internal_fns[i];
268 }
269 
270 hsa_op_reg *
get_shadow_reg()271 hsa_function_representation::get_shadow_reg ()
272 {
273   /* If we compile a function with kernel dispatch and does not set
274      an optimization level, the function won't be inlined and
275      we return NULL.  */
276   if (!m_kern_p)
277     return NULL;
278 
279   if (m_shadow_reg)
280     return m_shadow_reg;
281 
282   /* Append the shadow argument.  */
283   hsa_symbol *shadow = new hsa_symbol (BRIG_TYPE_U64, BRIG_SEGMENT_KERNARG,
284 				       BRIG_LINKAGE_FUNCTION);
285   m_input_args.safe_push (shadow);
286   shadow->m_name = "hsa_runtime_shadow";
287 
288   hsa_op_reg *r = new hsa_op_reg (BRIG_TYPE_U64);
289   hsa_op_address *addr = new hsa_op_address (shadow);
290 
291   hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, BRIG_TYPE_U64, r, addr);
292   hsa_bb_for_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun))->append_insn (mem);
293   m_shadow_reg = r;
294 
295   return r;
296 }
297 
has_shadow_reg_p()298 bool hsa_function_representation::has_shadow_reg_p ()
299 {
300   return m_shadow_reg != NULL;
301 }
302 
303 void
init_extra_bbs()304 hsa_function_representation::init_extra_bbs ()
305 {
306   hsa_init_new_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun));
307   hsa_init_new_bb (EXIT_BLOCK_PTR_FOR_FN (cfun));
308 }
309 
310 void
update_dominance()311 hsa_function_representation::update_dominance ()
312 {
313   if (m_modified_cfg)
314     {
315       free_dominance_info (CDI_DOMINATORS);
316       calculate_dominance_info (CDI_DOMINATORS);
317     }
318 }
319 
320 hsa_symbol *
create_hsa_temporary(BrigType16_t type)321 hsa_function_representation::create_hsa_temporary (BrigType16_t type)
322 {
323   hsa_symbol *s = new hsa_symbol (type, BRIG_SEGMENT_PRIVATE,
324 				  BRIG_LINKAGE_FUNCTION);
325   s->m_name_number = m_temp_symbol_count++;
326 
327   hsa_cfun->m_private_variables.safe_push (s);
328   return s;
329 }
330 
331 BrigLinkage8_t
get_linkage()332 hsa_function_representation::get_linkage ()
333 {
334   if (m_internal_fn)
335     return BRIG_LINKAGE_PROGRAM;
336 
337   return m_kern_p || TREE_PUBLIC (m_decl) ?
338     BRIG_LINKAGE_PROGRAM : BRIG_LINKAGE_MODULE;
339 }
340 
341 /* Hash map of simple OMP builtins.  */
342 static hash_map <nofree_string_hash, omp_simple_builtin> *omp_simple_builtins
343   = NULL;
344 
345 /* Warning messages for OMP builtins.  */
346 
347 #define HSA_WARN_LOCK_ROUTINE "support for HSA does not implement OpenMP " \
348   "lock routines"
349 #define HSA_WARN_TIMING_ROUTINE "support for HSA does not implement OpenMP " \
350   "timing routines"
351 #define HSA_WARN_MEMORY_ROUTINE "OpenMP device memory library routines have " \
352   "undefined semantics within target regions, support for HSA ignores them"
353 #define HSA_WARN_AFFINITY "Support for HSA does not implement OpenMP " \
354   "affinity feateres"
355 
356 /* Initialize hash map with simple OMP builtins.  */
357 
358 static void
hsa_init_simple_builtins()359 hsa_init_simple_builtins ()
360 {
361   if (omp_simple_builtins != NULL)
362     return;
363 
364   omp_simple_builtins
365     = new hash_map <nofree_string_hash, omp_simple_builtin> ();
366 
367   omp_simple_builtin omp_builtins[] =
368     {
369       omp_simple_builtin ("omp_get_initial_device", NULL, false,
370 			  new hsa_op_immed (GOMP_DEVICE_HOST,
371 					    (BrigType16_t) BRIG_TYPE_S32)),
372       omp_simple_builtin ("omp_is_initial_device", NULL, false,
373 			  new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
374       omp_simple_builtin ("omp_get_dynamic", NULL, false,
375 			  new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
376       omp_simple_builtin ("omp_set_dynamic", NULL, false, NULL),
377       omp_simple_builtin ("omp_init_lock", HSA_WARN_LOCK_ROUTINE, true),
378       omp_simple_builtin ("omp_init_lock_with_hint", HSA_WARN_LOCK_ROUTINE,
379 			  true),
380       omp_simple_builtin ("omp_init_nest_lock_with_hint", HSA_WARN_LOCK_ROUTINE,
381 			  true),
382       omp_simple_builtin ("omp_destroy_lock", HSA_WARN_LOCK_ROUTINE, true),
383       omp_simple_builtin ("omp_set_lock", HSA_WARN_LOCK_ROUTINE, true),
384       omp_simple_builtin ("omp_unset_lock", HSA_WARN_LOCK_ROUTINE, true),
385       omp_simple_builtin ("omp_test_lock", HSA_WARN_LOCK_ROUTINE, true),
386       omp_simple_builtin ("omp_get_wtime", HSA_WARN_TIMING_ROUTINE, true),
387       omp_simple_builtin ("omp_get_wtick", HSA_WARN_TIMING_ROUTINE, true),
388       omp_simple_builtin ("omp_target_alloc", HSA_WARN_MEMORY_ROUTINE, false,
389 			  new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_U64)),
390       omp_simple_builtin ("omp_target_free", HSA_WARN_MEMORY_ROUTINE, false),
391       omp_simple_builtin ("omp_target_is_present", HSA_WARN_MEMORY_ROUTINE,
392 			  false,
393 			  new hsa_op_immed (-1, (BrigType16_t) BRIG_TYPE_S32)),
394       omp_simple_builtin ("omp_target_memcpy", HSA_WARN_MEMORY_ROUTINE, false,
395 			  new hsa_op_immed (-1, (BrigType16_t) BRIG_TYPE_S32)),
396       omp_simple_builtin ("omp_target_memcpy_rect", HSA_WARN_MEMORY_ROUTINE,
397 			  false,
398 			  new hsa_op_immed (-1, (BrigType16_t) BRIG_TYPE_S32)),
399       omp_simple_builtin ("omp_target_associate_ptr", HSA_WARN_MEMORY_ROUTINE,
400 			  false,
401 			  new hsa_op_immed (-1, (BrigType16_t) BRIG_TYPE_S32)),
402       omp_simple_builtin ("omp_target_disassociate_ptr",
403 			  HSA_WARN_MEMORY_ROUTINE,
404 			  false,
405 			  new hsa_op_immed (-1, (BrigType16_t) BRIG_TYPE_S32)),
406       omp_simple_builtin ("omp_set_max_active_levels",
407 			  "Support for HSA only allows only one active level, "
408 			  "call to omp_set_max_active_levels will be ignored "
409 			  "in the generated HSAIL",
410 			  false, NULL),
411       omp_simple_builtin ("omp_get_max_active_levels", NULL, false,
412 			  new hsa_op_immed (1, (BrigType16_t) BRIG_TYPE_S32)),
413       omp_simple_builtin ("omp_in_final", NULL, false,
414 			  new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
415       omp_simple_builtin ("omp_get_proc_bind", HSA_WARN_AFFINITY, false,
416 			  new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
417       omp_simple_builtin ("omp_get_num_places", HSA_WARN_AFFINITY, false,
418 			  new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
419       omp_simple_builtin ("omp_get_place_num_procs", HSA_WARN_AFFINITY, false,
420 			  new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
421       omp_simple_builtin ("omp_get_place_proc_ids", HSA_WARN_AFFINITY, false,
422 			  NULL),
423       omp_simple_builtin ("omp_get_place_num", HSA_WARN_AFFINITY, false,
424 			  new hsa_op_immed (-1, (BrigType16_t) BRIG_TYPE_S32)),
425       omp_simple_builtin ("omp_get_partition_num_places", HSA_WARN_AFFINITY,
426 			  false,
427 			  new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
428       omp_simple_builtin ("omp_get_partition_place_nums", HSA_WARN_AFFINITY,
429 			  false, NULL),
430       omp_simple_builtin ("omp_set_default_device",
431 			  "omp_set_default_device has undefined semantics "
432 			  "within target regions, support for HSA ignores it",
433 			  false, NULL),
434       omp_simple_builtin ("omp_get_default_device",
435 			  "omp_get_default_device has undefined semantics "
436 			  "within target regions, support for HSA ignores it",
437 			  false,
438 			  new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
439       omp_simple_builtin ("omp_get_num_devices",
440 			  "omp_get_num_devices has undefined semantics "
441 			  "within target regions, support for HSA ignores it",
442 			  false,
443 			  new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
444       omp_simple_builtin ("omp_get_num_procs", NULL, true, NULL),
445       omp_simple_builtin ("omp_get_cancellation", NULL, true, NULL),
446       omp_simple_builtin ("omp_set_nested", NULL, true, NULL),
447       omp_simple_builtin ("omp_get_nested", NULL, true, NULL),
448       omp_simple_builtin ("omp_set_schedule", NULL, true, NULL),
449       omp_simple_builtin ("omp_get_schedule", NULL, true, NULL),
450       omp_simple_builtin ("omp_get_thread_limit", NULL, true, NULL),
451       omp_simple_builtin ("omp_get_team_size", NULL, true, NULL),
452       omp_simple_builtin ("omp_get_ancestor_thread_num", NULL, true, NULL),
453       omp_simple_builtin ("omp_get_max_task_priority", NULL, true, NULL)
454     };
455 
456   unsigned count = sizeof (omp_builtins) / sizeof (omp_simple_builtin);
457 
458   for (unsigned i = 0; i < count; i++)
459     omp_simple_builtins->put (omp_builtins[i].m_name, omp_builtins[i]);
460 }
461 
462 /* Allocate HSA structures that we need only while generating with this.  */
463 
464 static void
hsa_init_data_for_cfun()465 hsa_init_data_for_cfun ()
466 {
467   hsa_init_compilation_unit_data ();
468   gcc_obstack_init (&hsa_obstack);
469 }
470 
471 /* Deinitialize HSA subsystem and free all allocated memory.  */
472 
473 static void
hsa_deinit_data_for_cfun(void)474 hsa_deinit_data_for_cfun (void)
475 {
476   basic_block bb;
477 
478   FOR_ALL_BB_FN (bb, cfun)
479     if (bb->aux)
480       {
481 	hsa_bb *hbb = hsa_bb_for_bb (bb);
482 	hbb->~hsa_bb ();
483 	bb->aux = NULL;
484       }
485 
486   for (unsigned int i = 0; i < hsa_operands.length (); i++)
487     hsa_destroy_operand (hsa_operands[i]);
488 
489   hsa_operands.release ();
490 
491   for (unsigned i = 0; i < hsa_instructions.length (); i++)
492     hsa_destroy_insn (hsa_instructions[i]);
493 
494   hsa_instructions.release ();
495 
496   if (omp_simple_builtins != NULL)
497     {
498       delete omp_simple_builtins;
499       omp_simple_builtins = NULL;
500     }
501 
502   obstack_free (&hsa_obstack, NULL);
503   delete hsa_cfun;
504 }
505 
506 /* Return the type which holds addresses in the given SEGMENT.  */
507 
508 static BrigType16_t
hsa_get_segment_addr_type(BrigSegment8_t segment)509 hsa_get_segment_addr_type (BrigSegment8_t segment)
510 {
511   switch (segment)
512     {
513     case BRIG_SEGMENT_NONE:
514       gcc_unreachable ();
515 
516     case BRIG_SEGMENT_FLAT:
517     case BRIG_SEGMENT_GLOBAL:
518     case BRIG_SEGMENT_READONLY:
519     case BRIG_SEGMENT_KERNARG:
520       return hsa_machine_large_p () ? BRIG_TYPE_U64 : BRIG_TYPE_U32;
521 
522     case BRIG_SEGMENT_GROUP:
523     case BRIG_SEGMENT_PRIVATE:
524     case BRIG_SEGMENT_SPILL:
525     case BRIG_SEGMENT_ARG:
526       return BRIG_TYPE_U32;
527     }
528   gcc_unreachable ();
529 }
530 
531 /* Return integer brig type according to provided SIZE in bytes.  If SIGN
532    is set to true, return signed integer type.  */
533 
534 static BrigType16_t
get_integer_type_by_bytes(unsigned size,bool sign)535 get_integer_type_by_bytes (unsigned size, bool sign)
536 {
537   if (sign)
538     switch (size)
539       {
540       case 1:
541 	return BRIG_TYPE_S8;
542       case 2:
543 	return BRIG_TYPE_S16;
544       case 4:
545 	return BRIG_TYPE_S32;
546       case 8:
547 	return BRIG_TYPE_S64;
548       default:
549 	break;
550       }
551   else
552     switch (size)
553       {
554       case 1:
555 	return BRIG_TYPE_U8;
556       case 2:
557 	return BRIG_TYPE_U16;
558       case 4:
559 	return BRIG_TYPE_U32;
560       case 8:
561 	return BRIG_TYPE_U64;
562       default:
563 	break;
564       }
565 
566   return 0;
567 }
568 
569 /* If T points to an integral type smaller than 32 bits, change it to a 32bit
570    equivalent and return the result.  Otherwise just return the result.   */
571 
572 static BrigType16_t
hsa_extend_inttype_to_32bit(BrigType16_t t)573 hsa_extend_inttype_to_32bit (BrigType16_t t)
574 {
575   if (t == BRIG_TYPE_U8 || t == BRIG_TYPE_U16)
576     return BRIG_TYPE_U32;
577   else if (t == BRIG_TYPE_S8 || t == BRIG_TYPE_S16)
578     return BRIG_TYPE_S32;
579   return t;
580 }
581 
582 /* Return HSA type for tree TYPE, which has to fit into BrigType16_t.  Pointers
583    are assumed to use flat addressing.  If min32int is true, always expand
584    integer types to one that has at least 32 bits.  */
585 
586 static BrigType16_t
hsa_type_for_scalar_tree_type(const_tree type,bool min32int)587 hsa_type_for_scalar_tree_type (const_tree type, bool min32int)
588 {
589   HOST_WIDE_INT bsize;
590   const_tree base;
591   BrigType16_t res = BRIG_TYPE_NONE;
592 
593   gcc_checking_assert (TYPE_P (type));
594   gcc_checking_assert (!AGGREGATE_TYPE_P (type));
595   if (POINTER_TYPE_P (type))
596     return hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
597 
598   if (TREE_CODE (type) == VECTOR_TYPE)
599     base = TREE_TYPE (type);
600   else if (TREE_CODE (type) == COMPLEX_TYPE)
601     {
602       base = TREE_TYPE (type);
603       min32int = true;
604     }
605   else
606     base = type;
607 
608   if (!tree_fits_uhwi_p (TYPE_SIZE (base)))
609     {
610       HSA_SORRY_ATV (EXPR_LOCATION (type),
611 		     "support for HSA does not implement huge or "
612 		     "variable-sized type %qT", type);
613       return res;
614     }
615 
616   bsize = tree_to_uhwi (TYPE_SIZE (base));
617   unsigned byte_size = bsize / BITS_PER_UNIT;
618   if (INTEGRAL_TYPE_P (base))
619     res = get_integer_type_by_bytes (byte_size, !TYPE_UNSIGNED (base));
620   else if (SCALAR_FLOAT_TYPE_P (base))
621     {
622       switch (bsize)
623 	{
624 	case 16:
625 	  res = BRIG_TYPE_F16;
626 	  break;
627 	case 32:
628 	  res = BRIG_TYPE_F32;
629 	  break;
630 	case 64:
631 	  res = BRIG_TYPE_F64;
632 	  break;
633 	default:
634 	  break;
635 	}
636     }
637 
638   if (res == BRIG_TYPE_NONE)
639     {
640       HSA_SORRY_ATV (EXPR_LOCATION (type),
641 		     "support for HSA does not implement type %qT", type);
642       return res;
643     }
644 
645   if (TREE_CODE (type) == VECTOR_TYPE)
646     {
647       HOST_WIDE_INT tsize = tree_to_uhwi (TYPE_SIZE (type));
648 
649       if (bsize == tsize)
650 	{
651 	  HSA_SORRY_ATV (EXPR_LOCATION (type),
652 			 "support for HSA does not implement a vector type "
653 			 "where a type and unit size are equal: %qT", type);
654 	  return res;
655 	}
656 
657       switch (tsize)
658 	{
659 	case 32:
660 	  res |= BRIG_TYPE_PACK_32;
661 	  break;
662 	case 64:
663 	  res |= BRIG_TYPE_PACK_64;
664 	  break;
665 	case 128:
666 	  res |= BRIG_TYPE_PACK_128;
667 	  break;
668 	default:
669 	  HSA_SORRY_ATV (EXPR_LOCATION (type),
670 			 "support for HSA does not implement type %qT", type);
671 	}
672     }
673 
674   if (min32int)
675     /* Registers/immediate operands can only be 32bit or more except for
676        f16.  */
677     res = hsa_extend_inttype_to_32bit (res);
678 
679   if (TREE_CODE (type) == COMPLEX_TYPE)
680     {
681       unsigned bsize = 2 * hsa_type_bit_size (res);
682       res = hsa_bittype_for_bitsize (bsize);
683     }
684 
685   return res;
686 }
687 
688 /* Returns the BRIG type we need to load/store entities of TYPE.  */
689 
690 static BrigType16_t
mem_type_for_type(BrigType16_t type)691 mem_type_for_type (BrigType16_t type)
692 {
693   /* HSA has non-intuitive constraints on load/store types.  If it's
694      a bit-type it _must_ be B128, if it's not a bit-type it must be
695      64bit max.  So for loading entities of 128 bits (e.g. vectors)
696      we have to use B128, while for loading the rest we have to use the
697      input type (??? or maybe also flattened to a equally sized non-vector
698      unsigned type?).  */
699   if ((type & BRIG_TYPE_PACK_MASK) == BRIG_TYPE_PACK_128)
700     return BRIG_TYPE_B128;
701   else if (hsa_btype_p (type) || hsa_type_packed_p (type))
702     {
703       unsigned bitsize = hsa_type_bit_size (type);
704       if (bitsize < 128)
705 	return hsa_uint_for_bitsize (bitsize);
706       else
707 	return hsa_bittype_for_bitsize (bitsize);
708     }
709   return type;
710 }
711 
712 /* Return HSA type for tree TYPE.  If it cannot fit into BrigType16_t, some
713    kind of array will be generated, setting DIM appropriately.  Otherwise, it
714    will be set to zero.  */
715 
716 static BrigType16_t
717 hsa_type_for_tree_type (const_tree type, unsigned HOST_WIDE_INT *dim_p = NULL,
718 			bool min32int = false)
719 {
720   gcc_checking_assert (TYPE_P (type));
721   if (!tree_fits_uhwi_p (TYPE_SIZE_UNIT (type)))
722     {
723       HSA_SORRY_ATV (EXPR_LOCATION (type), "support for HSA does not "
724 		     "implement huge or variable-sized type %qT", type);
725       return BRIG_TYPE_NONE;
726     }
727 
728   if (RECORD_OR_UNION_TYPE_P (type))
729     {
730       if (dim_p)
731 	*dim_p = tree_to_uhwi (TYPE_SIZE_UNIT (type));
732       return BRIG_TYPE_U8 | BRIG_TYPE_ARRAY;
733     }
734 
735   if (TREE_CODE (type) == ARRAY_TYPE)
736     {
737       /* We try to be nice and use the real base-type when this is an array of
738 	 scalars and only resort to an array of bytes if the type is more
739 	 complex.  */
740 
741       unsigned HOST_WIDE_INT dim = 1;
742 
743       while (TREE_CODE (type) == ARRAY_TYPE)
744 	{
745 	  tree domain = TYPE_DOMAIN (type);
746 	  if (!TYPE_MIN_VALUE (domain)
747 	      || !TYPE_MAX_VALUE (domain)
748 	      || !tree_fits_shwi_p (TYPE_MIN_VALUE (domain))
749 	      || !tree_fits_shwi_p (TYPE_MAX_VALUE (domain)))
750 	    {
751 	      HSA_SORRY_ATV (EXPR_LOCATION (type),
752 			     "support for HSA does not implement array "
753 			     "%qT with unknown bounds", type);
754 	      return BRIG_TYPE_NONE;
755 	    }
756 	  HOST_WIDE_INT min = tree_to_shwi (TYPE_MIN_VALUE (domain));
757 	  HOST_WIDE_INT max = tree_to_shwi (TYPE_MAX_VALUE (domain));
758 	  dim = dim * (unsigned HOST_WIDE_INT) (max - min + 1);
759 	  type = TREE_TYPE (type);
760 	}
761 
762       BrigType16_t res;
763       if (RECORD_OR_UNION_TYPE_P (type))
764 	{
765 	  dim = dim * tree_to_uhwi (TYPE_SIZE_UNIT (type));
766 	  res = BRIG_TYPE_U8;
767 	}
768       else
769 	res = hsa_type_for_scalar_tree_type (type, false);
770 
771       if (dim_p)
772 	*dim_p = dim;
773       return res | BRIG_TYPE_ARRAY;
774     }
775 
776   /* Scalar case: */
777   if (dim_p)
778     *dim_p = 0;
779 
780   return hsa_type_for_scalar_tree_type (type, min32int);
781 }
782 
783 /* Returns true if converting from STYPE into DTYPE needs the _CVT
784    opcode.  If false a normal _MOV is enough.  */
785 
786 static bool
hsa_needs_cvt(BrigType16_t dtype,BrigType16_t stype)787 hsa_needs_cvt (BrigType16_t dtype, BrigType16_t stype)
788 {
789   if (hsa_btype_p (dtype))
790     return false;
791 
792   /* float <-> int conversions are real converts.  */
793   if (hsa_type_float_p (dtype) != hsa_type_float_p (stype))
794     return true;
795   /* When both types have different size, then we need CVT as well.  */
796   if (hsa_type_bit_size (dtype) != hsa_type_bit_size (stype))
797     return true;
798   return false;
799 }
800 
801 /* Return declaration name if it exists or create one from UID if it does not.
802    If DECL is a local variable, make UID part of its name.  */
803 
804 const char *
hsa_get_declaration_name(tree decl)805 hsa_get_declaration_name (tree decl)
806 {
807   if (!DECL_NAME (decl))
808     {
809       char buf[64];
810       snprintf (buf, 64, "__hsa_anon_%u", DECL_UID (decl));
811       size_t len = strlen (buf);
812       char *copy = (char *) obstack_alloc (&hsa_obstack, len + 1);
813       memcpy (copy, buf, len + 1);
814       return copy;
815     }
816 
817   tree name_tree;
818   if (TREE_CODE (decl) == FUNCTION_DECL
819       || (TREE_CODE (decl) == VAR_DECL && is_global_var (decl)))
820     name_tree = DECL_ASSEMBLER_NAME (decl);
821   else
822     name_tree = DECL_NAME (decl);
823 
824   const char *name = IDENTIFIER_POINTER (name_tree);
825   /* User-defined assembly names have prepended asterisk symbol.  */
826   if (name[0] == '*')
827     name++;
828 
829   if ((TREE_CODE (decl) == VAR_DECL)
830       && decl_function_context (decl))
831     {
832       size_t len = strlen (name);
833       char *buf = (char *) alloca (len + 32);
834       snprintf (buf, len + 32, "%s_%u", name, DECL_UID (decl));
835       len = strlen (buf);
836       char *copy = (char *) obstack_alloc (&hsa_obstack, len + 1);
837       memcpy (copy, buf, len + 1);
838       return copy;
839     }
840   else
841     return name;
842 }
843 
844 /* Lookup or create the associated hsa_symbol structure with a given VAR_DECL
845    or lookup the hsa_structure corresponding to a PARM_DECL.  */
846 
847 static hsa_symbol *
get_symbol_for_decl(tree decl)848 get_symbol_for_decl (tree decl)
849 {
850   hsa_symbol **slot;
851   hsa_symbol dummy (BRIG_TYPE_NONE, BRIG_SEGMENT_NONE, BRIG_LINKAGE_NONE);
852 
853   gcc_assert (TREE_CODE (decl) == PARM_DECL
854 	      || TREE_CODE (decl) == RESULT_DECL
855 	      || TREE_CODE (decl) == VAR_DECL
856 	      || TREE_CODE (decl) == CONST_DECL);
857 
858   dummy.m_decl = decl;
859 
860   bool is_in_global_vars = ((TREE_CODE (decl) == VAR_DECL)
861 			    && !decl_function_context (decl));
862 
863   if (is_in_global_vars)
864     slot = hsa_global_variable_symbols->find_slot (&dummy, INSERT);
865   else
866     slot = hsa_cfun->m_local_symbols->find_slot (&dummy, INSERT);
867 
868   gcc_checking_assert (slot);
869   if (*slot)
870     {
871       hsa_symbol *sym = (*slot);
872 
873       /* If the symbol is problematic, mark current function also as
874 	 problematic.  */
875       if (sym->m_seen_error)
876 	hsa_fail_cfun ();
877 
878       /* PR hsa/70234: If a global variable was marked to be emitted,
879 	 but HSAIL generation of a function using the variable fails,
880 	 we should retry to emit the variable in context of a different
881 	 function.
882 
883 	 Iterate elements whether a symbol is already in m_global_symbols
884 	 of not.  */
885         if (is_in_global_vars && !sym->m_emitted_to_brig)
886 	  {
887 	    for (unsigned i = 0; i < hsa_cfun->m_global_symbols.length (); i++)
888 	      if (hsa_cfun->m_global_symbols[i] == sym)
889 		return *slot;
890 	    hsa_cfun->m_global_symbols.safe_push (sym);
891 	  }
892 
893       return *slot;
894     }
895   else
896     {
897       hsa_symbol *sym;
898       /* PARM_DECLs and RESULT_DECL should be already in m_local_symbols.  */
899       gcc_assert (TREE_CODE (decl) == VAR_DECL
900 		  || TREE_CODE (decl) == CONST_DECL);
901       BrigAlignment8_t align = hsa_object_alignment (decl);
902 
903       if (is_in_global_vars)
904 	{
905 	  gcc_checking_assert (TREE_CODE (decl) != CONST_DECL);
906 	  sym = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_GLOBAL,
907 				BRIG_LINKAGE_PROGRAM, true,
908 				BRIG_ALLOCATION_PROGRAM, align);
909 	  hsa_cfun->m_global_symbols.safe_push (sym);
910 	  sym->fillup_for_decl (decl);
911 	  if (sym->m_align > align)
912 	    {
913 	      sym->m_seen_error = true;
914 	      HSA_SORRY_ATV (EXPR_LOCATION (decl),
915 			     "HSA specification requires that %E is at least "
916 			     "naturally aligned", decl);
917 	    }
918 	}
919       else
920 	{
921 	  /* As generation of efficient memory copy instructions relies
922 	     on alignment greater or equal to 8 bytes,
923 	     we need to increase alignment of all aggregate types.. */
924 	  if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
925 	    align = MAX ((BrigAlignment8_t) BRIG_ALIGNMENT_8, align);
926 
927 	  BrigAllocation allocation = BRIG_ALLOCATION_AUTOMATIC;
928 	  BrigSegment8_t segment;
929 	  if (TREE_CODE (decl) == CONST_DECL)
930 	    {
931 	      segment = BRIG_SEGMENT_READONLY;
932 	      allocation = BRIG_ALLOCATION_AGENT;
933 	    }
934 	  else if (lookup_attribute ("hsa_group_segment",
935 				     DECL_ATTRIBUTES (decl)))
936 	    segment = BRIG_SEGMENT_GROUP;
937 	  else if (TREE_STATIC (decl))
938 	    {
939 	      segment = BRIG_SEGMENT_GLOBAL;
940 	      allocation = BRIG_ALLOCATION_PROGRAM;
941 	    }
942 	  else if (lookup_attribute ("hsa_global_segment",
943 				     DECL_ATTRIBUTES (decl)))
944 	    segment = BRIG_SEGMENT_GLOBAL;
945 	  else
946 	    segment = BRIG_SEGMENT_PRIVATE;
947 
948 	  sym = new hsa_symbol (BRIG_TYPE_NONE, segment, BRIG_LINKAGE_FUNCTION,
949 				false, allocation, align);
950 	  sym->fillup_for_decl (decl);
951 	  hsa_cfun->m_private_variables.safe_push (sym);
952 	}
953 
954       sym->m_name = hsa_get_declaration_name (decl);
955       *slot = sym;
956       return sym;
957     }
958 }
959 
960 /* For a given HSA function declaration, return a host
961    function declaration.  */
962 
963 tree
hsa_get_host_function(tree decl)964 hsa_get_host_function (tree decl)
965 {
966   hsa_function_summary *s = hsa_summaries->get (cgraph_node::get_create (decl));
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 *
get_brig_function_name(tree decl)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 != NULL
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 *
hsa_get_spill_symbol(BrigType16_t type)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 *
hsa_get_string_cst_symbol(tree string_cst)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
hsa_fixup_mov_insn_type(hsa_insn_basic * insn)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 
hsa_op_base(BrigKind16_t k)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 
hsa_op_with_type(BrigKind16_t k,BrigType16_t t)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 *
get_in_type(BrigType16_t dtype,hsa_bb * hbb)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 *
extend_int_to_32bit(hsa_bb * hbb)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 
hsa_op_immed(tree tree_val,bool min32int)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 
hsa_op_immed(HOST_WIDE_INT integer_value,BrigType16_t type)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 
hsa_op_immed()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 *
new(size_t size)1158 hsa_op_immed::operator new (size_t size)
1159 {
1160   return obstack_alloc (&hsa_obstack, size);
1161 }
1162 
1163 /* Destructor.  */
1164 
~hsa_op_immed()1165 hsa_op_immed::~hsa_op_immed ()
1166 {
1167 }
1168 
1169 /* Change type of the immediate value to T.  */
1170 
1171 void
set_type(BrigType16_t t)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 
hsa_op_reg(BrigType16_t t)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 *
new(size_t size)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
verify_ssa()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 
hsa_op_address(hsa_symbol * sym,hsa_op_reg * r,HOST_WIDE_INT offset)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 
hsa_op_address(hsa_symbol * sym,HOST_WIDE_INT offset)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 
hsa_op_address(hsa_op_reg * r,HOST_WIDE_INT offset)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 *
new(size_t size)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 
hsa_op_code_ref()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 
hsa_op_code_list(unsigned elements)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 *
new(size_t size)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 
hsa_op_operand_list(unsigned elements)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 *
new(size_t size)1317 hsa_op_operand_list::operator new (size_t size)
1318 {
1319   return obstack_alloc (&hsa_obstack, size);
1320 }
1321 
~hsa_op_operand_list()1322 hsa_op_operand_list::~hsa_op_operand_list ()
1323 {
1324   m_offsets.release ();
1325 }
1326 
1327 
1328 hsa_op_reg *
reg_for_gimple_ssa(tree ssa)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
set_definition(hsa_insn_basic * insn)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 
hsa_insn_basic(unsigned nops,int opc)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
set_op(int index,hsa_op_base * op)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 *
get_op(int index)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 **
get_op_addr(int index)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
operand_count()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 
hsa_insn_basic(unsigned nops,int opc,BrigType16_t t,hsa_op_base * arg0,hsa_op_base * arg1,hsa_op_base * arg2,hsa_op_base * arg3)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 *
new(size_t size)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
verify()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 
hsa_insn_phi(unsigned nops,hsa_op_reg * dst)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 
hsa_insn_br(unsigned nops,int opc,BrigType16_t t,BrigWidth8_t width,hsa_op_base * arg0,hsa_op_base * arg1,hsa_op_base * arg2,hsa_op_base * arg3)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 
hsa_insn_cbr(hsa_op_reg * ctrl)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 
hsa_insn_sbr(hsa_op_reg * index,unsigned jump_count)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
replace_all_labels(basic_block old_bb,basic_block new_bb)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 
~hsa_insn_sbr()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 
hsa_insn_cmp(BrigCompareOperation8_t cmp,BrigType16_t t,hsa_op_base * arg0,hsa_op_base * arg1,hsa_op_base * arg2)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 
hsa_insn_mem(int opc,BrigType16_t t,hsa_op_base * arg0,hsa_op_base * arg1)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 
hsa_insn_mem(unsigned nops,int opc,BrigType16_t t,hsa_op_base * arg0,hsa_op_base * arg1,hsa_op_base * arg2,hsa_op_base * arg3)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 
hsa_insn_atomic(int nops,int opc,enum BrigAtomicOperation aop,BrigType16_t t,BrigMemoryOrder memorder,hsa_op_base * arg0,hsa_op_base * arg1,hsa_op_base * arg2,hsa_op_base * arg3)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 
hsa_insn_signal(int nops,int opc,enum BrigAtomicOperation sop,BrigType16_t t,BrigMemoryOrder memorder,hsa_op_base * arg0,hsa_op_base * arg1,hsa_op_base * arg2,hsa_op_base * arg3)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 
hsa_insn_seg(int opc,BrigType16_t dest,BrigType16_t srct,BrigSegment8_t seg,hsa_op_base * arg0,hsa_op_base * arg1)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 
hsa_insn_call(tree callee)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 
hsa_insn_call(hsa_internal_fn * fn)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 
~hsa_insn_call()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.  */
hsa_insn_arg_block(BrigKind brig_kind,hsa_insn_call * call)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 
hsa_insn_comment(const char * s)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 
~hsa_insn_comment()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 
hsa_insn_queue(int nops,int opcode,BrigSegment segment,BrigMemoryOrder memory_order,hsa_op_base * arg0,hsa_op_base * arg1,hsa_op_base * arg2,hsa_op_base * arg3)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)
hsa_insn_basic(nops,opcode,destt,arg0,arg1,arg2)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 
hsa_insn_packed(int nops,BrigOpcode opcode,BrigType16_t destt,BrigType16_t srct,hsa_op_base * arg0,hsa_op_base * arg1,hsa_op_base * arg2)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 
hsa_insn_cvt(hsa_op_with_type * dest,hsa_op_with_type * src)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 
hsa_insn_alloca(hsa_op_with_type * dest,hsa_op_with_type * size,unsigned alignment)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
append_insn(hsa_insn_basic * insn)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
append_phi(hsa_insn_phi * hphi)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
hsa_insert_insn_before(hsa_insn_basic * new_insn,hsa_insn_basic * old_insn)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
hsa_append_insn_after(hsa_insn_basic * new_insn,hsa_insn_basic * old_insn)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 *
gen_address_calculation(tree exp,hsa_bb * hbb,BrigType16_t addrtype)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 *
add_addr_regs_if_needed(hsa_op_reg * r1,hsa_op_reg * r2,hsa_bb * hbb)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
process_mem_base(tree base,hsa_symbol ** symbol,BrigType16_t * addrtype,hsa_op_reg ** reg,offset_int * offset,hsa_bb * hbb)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 *
gen_hsa_addr_with_align(tree ref,hsa_bb * hbb,BrigAlignment8_t * output_align)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 *
gen_hsa_addr_for_arg(tree tree_type,int index)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
convert_addr_to_flat_segment(hsa_op_address * addr,hsa_op_reg * dest,hsa_bb * hbb)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
gen_hsa_addr_insns(tree val,hsa_op_reg * dest,hsa_bb * hbb)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_DECL%> 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 *
hsa_reg_or_immed_for_gimple_op(tree op,hsa_bb * hbb)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
hsa_build_append_simple_mov(hsa_op_reg * dest,hsa_op_base * src,hsa_bb * hbb)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
gen_hsa_insns_for_bitfield(hsa_op_reg * dest,hsa_op_reg * value_reg,HOST_WIDE_INT bitsize,HOST_WIDE_INT bitpos,hsa_bb * hbb)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
gen_hsa_insns_for_bitfield_load(hsa_op_reg * dest,hsa_op_address * addr,HOST_WIDE_INT bitsize,HOST_WIDE_INT bitpos,hsa_bb * hbb,BrigAlignment8_t align)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
hsa_bitmemref_alignment(tree ref)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
gen_hsa_insns_for_load(hsa_op_reg * dest,tree rhs,tree type,hsa_bb * hbb)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
get_bitfield_size(unsigned bitpos,unsigned bitsize)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
gen_hsa_insns_for_store(tree lhs,hsa_op_base * src,hsa_bb * hbb)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
gen_hsa_memory_copy(hsa_bb * hbb,hsa_op_address * target,hsa_op_address * src,unsigned size,BrigAlignment8_t min_align)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
build_memset_value(unsigned HOST_WIDE_INT constant,unsigned byte_size)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
gen_hsa_memory_set(hsa_bb * hbb,hsa_op_address * target,unsigned HOST_WIDE_INT constant,unsigned size,BrigAlignment8_t min_align)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
gen_hsa_ctor_assignment(hsa_op_address * addr_lhs,tree rhs,hsa_bb * hbb,BrigAlignment8_t align)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
gen_hsa_insns_for_single_assignment(tree lhs,tree rhs,hsa_bb * hbb)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 *
hsa_spill_in(hsa_insn_basic * insn,hsa_op_reg * spill_reg,hsa_op_reg ** ptmp2)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 *
hsa_spill_out(hsa_insn_basic * insn,hsa_op_reg * spill_reg,hsa_op_reg ** ptmp2)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
gen_hsa_cmp_insn_from_gimple(enum tree_code code,tree lhs,tree rhs,hsa_op_reg * dest,hsa_bb * hbb)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", 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
gen_hsa_unary_operation(BrigOpcode opcode,hsa_op_reg * dest,hsa_op_with_type * op1,hsa_bb * hbb)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
gen_hsa_binary_operation(int opcode,hsa_op_reg * dest,hsa_op_with_type * op1,hsa_op_with_type * op2,hsa_bb * hbb)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
gen_hsa_insns_for_operation_assignment(gimple * assign,hsa_bb * hbb)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 MIN_EXPR:
3182       opcode = BRIG_OPCODE_MIN;
3183       break;
3184     case MAX_EXPR:
3185       opcode = BRIG_OPCODE_MAX;
3186       break;
3187     case ABS_EXPR:
3188       opcode = BRIG_OPCODE_ABS;
3189       break;
3190     case LSHIFT_EXPR:
3191       opcode = BRIG_OPCODE_SHL;
3192       break;
3193     case RSHIFT_EXPR:
3194       opcode = BRIG_OPCODE_SHR;
3195       break;
3196     case LROTATE_EXPR:
3197     case RROTATE_EXPR:
3198       {
3199 	hsa_insn_basic *insn = NULL;
3200 	int code1 = code == LROTATE_EXPR ? BRIG_OPCODE_SHL : BRIG_OPCODE_SHR;
3201 	int code2 = code != LROTATE_EXPR ? BRIG_OPCODE_SHL : BRIG_OPCODE_SHR;
3202 	BrigType16_t btype = hsa_type_for_scalar_tree_type (TREE_TYPE (lhs),
3203 							    true);
3204 
3205 	hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
3206 	hsa_op_reg *op1 = new hsa_op_reg (btype);
3207 	hsa_op_reg *op2 = new hsa_op_reg (btype);
3208 	hsa_op_with_type *shift1 = hsa_reg_or_immed_for_gimple_op (rhs2, hbb);
3209 
3210 	tree type = TREE_TYPE (rhs2);
3211 	unsigned HOST_WIDE_INT bitsize = TREE_INT_CST_LOW (TYPE_SIZE (type));
3212 
3213 	hsa_op_with_type *shift2 = NULL;
3214 	if (TREE_CODE (rhs2) == INTEGER_CST)
3215 	  shift2 = new hsa_op_immed (bitsize - tree_to_uhwi (rhs2),
3216 				     BRIG_TYPE_U32);
3217 	else if (TREE_CODE (rhs2) == SSA_NAME)
3218 	  {
3219 	    hsa_op_reg *s = hsa_cfun->reg_for_gimple_ssa (rhs2);
3220 	    s = as_a <hsa_op_reg *> (s->extend_int_to_32bit (hbb));
3221 	    hsa_op_reg *d = new hsa_op_reg (s->m_type);
3222 	    hsa_op_immed *size_imm = new hsa_op_immed (bitsize, BRIG_TYPE_U32);
3223 
3224 	    insn = new hsa_insn_basic (3, BRIG_OPCODE_SUB, d->m_type,
3225 				       d, s, size_imm);
3226 	    hbb->append_insn (insn);
3227 
3228 	    shift2 = d;
3229 	  }
3230 	else
3231 	  gcc_unreachable ();
3232 
3233 	hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
3234 	gen_hsa_binary_operation (code1, op1, src, shift1, hbb);
3235 	gen_hsa_binary_operation (code2, op2, src, shift2, hbb);
3236 	gen_hsa_binary_operation (BRIG_OPCODE_OR, dest, op1, op2, hbb);
3237 
3238 	return;
3239       }
3240     case BIT_IOR_EXPR:
3241       opcode = BRIG_OPCODE_OR;
3242       break;
3243     case BIT_XOR_EXPR:
3244       opcode = BRIG_OPCODE_XOR;
3245       break;
3246     case BIT_AND_EXPR:
3247       opcode = BRIG_OPCODE_AND;
3248       break;
3249     case BIT_NOT_EXPR:
3250       opcode = BRIG_OPCODE_NOT;
3251       break;
3252     case FIX_TRUNC_EXPR:
3253       {
3254 	hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
3255 	hsa_op_with_type *v = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
3256 
3257 	if (hsa_needs_cvt (dest->m_type, v->m_type))
3258 	  {
3259 	    hsa_op_reg *tmp = new hsa_op_reg (v->m_type);
3260 
3261 	    hsa_insn_basic *insn = new hsa_insn_basic (2, BRIG_OPCODE_TRUNC,
3262 						       tmp->m_type, tmp, v);
3263 	    hbb->append_insn (insn);
3264 
3265 	    hsa_insn_basic *cvtinsn = new hsa_insn_cvt (dest, tmp);
3266 	    hbb->append_insn (cvtinsn);
3267 	  }
3268 	else
3269 	  {
3270 	    hsa_insn_basic *insn = new hsa_insn_basic (2, BRIG_OPCODE_TRUNC,
3271 						       dest->m_type, dest, v);
3272 	    hbb->append_insn (insn);
3273 	  }
3274 
3275 	return;
3276       }
3277       opcode = BRIG_OPCODE_TRUNC;
3278       break;
3279 
3280     case LT_EXPR:
3281     case LE_EXPR:
3282     case GT_EXPR:
3283     case GE_EXPR:
3284     case EQ_EXPR:
3285     case NE_EXPR:
3286     case UNORDERED_EXPR:
3287     case ORDERED_EXPR:
3288     case UNLT_EXPR:
3289     case UNLE_EXPR:
3290     case UNGT_EXPR:
3291     case UNGE_EXPR:
3292     case UNEQ_EXPR:
3293     case LTGT_EXPR:
3294       {
3295 	hsa_op_reg *dest
3296 	  = hsa_cfun->reg_for_gimple_ssa (gimple_assign_lhs (assign));
3297 
3298 	gen_hsa_cmp_insn_from_gimple (code, rhs1, rhs2, dest, hbb);
3299 	return;
3300       }
3301     case COND_EXPR:
3302       {
3303 	hsa_op_reg *dest
3304 	  = hsa_cfun->reg_for_gimple_ssa (gimple_assign_lhs (assign));
3305 	hsa_op_with_type *ctrl = NULL;
3306 	tree cond = rhs1;
3307 
3308 	if (CONSTANT_CLASS_P (cond) || TREE_CODE (cond) == SSA_NAME)
3309 	  ctrl = hsa_reg_or_immed_for_gimple_op (cond, hbb);
3310 	else
3311 	  {
3312 	    hsa_op_reg *r = new hsa_op_reg (BRIG_TYPE_B1);
3313 
3314 	    gen_hsa_cmp_insn_from_gimple (TREE_CODE (cond),
3315 				  TREE_OPERAND (cond, 0),
3316 				  TREE_OPERAND (cond, 1),
3317 				  r, hbb);
3318 
3319 	    ctrl = r;
3320 	  }
3321 
3322 	hsa_op_with_type *op2 = hsa_reg_or_immed_for_gimple_op (rhs2, hbb);
3323 	hsa_op_with_type *op3 = hsa_reg_or_immed_for_gimple_op (rhs3, hbb);
3324 	op2 = op2->extend_int_to_32bit (hbb);
3325 	op3 = op3->extend_int_to_32bit (hbb);
3326 
3327 	BrigType16_t type = hsa_extend_inttype_to_32bit (dest->m_type);
3328 	BrigType16_t utype = hsa_unsigned_type_for_type (type);
3329 	if (is_a <hsa_op_immed *> (op2))
3330 	  op2->m_type = utype;
3331 	if (is_a <hsa_op_immed *> (op3))
3332 	  op3->m_type = utype;
3333 
3334 	hsa_insn_basic *insn
3335 	  = new hsa_insn_basic (4, BRIG_OPCODE_CMOV,
3336 				hsa_bittype_for_type (type),
3337 				NULL, ctrl, op2, op3);
3338 
3339 	hbb->append_insn (insn);
3340 	insn->set_output_in_type (dest, 0, hbb);
3341 	return;
3342       }
3343     case COMPLEX_EXPR:
3344       {
3345 	hsa_op_reg *dest
3346 	  = hsa_cfun->reg_for_gimple_ssa (gimple_assign_lhs (assign));
3347 	hsa_op_with_type *rhs1_reg = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
3348 	rhs1_reg = rhs1_reg->extend_int_to_32bit (hbb);
3349 	hsa_op_with_type *rhs2_reg = hsa_reg_or_immed_for_gimple_op (rhs2, hbb);
3350 	rhs2_reg = rhs2_reg->extend_int_to_32bit (hbb);
3351 
3352 	if (hsa_seen_error ())
3353 	  return;
3354 
3355 	BrigType16_t src_type = hsa_bittype_for_type (rhs1_reg->m_type);
3356 	rhs1_reg = rhs1_reg->get_in_type (src_type, hbb);
3357 	rhs2_reg = rhs2_reg->get_in_type (src_type, hbb);
3358 
3359 	hsa_insn_packed *insn
3360 	  = new hsa_insn_packed (3, BRIG_OPCODE_COMBINE, dest->m_type, src_type,
3361 				 dest, rhs1_reg, rhs2_reg);
3362 	hbb->append_insn (insn);
3363 
3364 	return;
3365       }
3366     default:
3367       /* Implement others as we come across them.  */
3368       HSA_SORRY_ATV (gimple_location (assign),
3369 		     "support for HSA does not implement operation %s",
3370 		     get_tree_code_name (code));
3371       return;
3372     }
3373 
3374 
3375   hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
3376   hsa_op_with_type *op1 = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
3377   hsa_op_with_type *op2
3378     = rhs2 ? hsa_reg_or_immed_for_gimple_op (rhs2, hbb) : NULL;
3379 
3380   if (hsa_seen_error ())
3381     return;
3382 
3383   switch (rhs_class)
3384     {
3385     case GIMPLE_TERNARY_RHS:
3386       {
3387 	hsa_op_with_type *op3 = hsa_reg_or_immed_for_gimple_op (rhs3, hbb);
3388 	op3 = op3->extend_int_to_32bit (hbb);
3389 	hsa_insn_basic *insn = new hsa_insn_basic (4, opcode, dest->m_type, dest,
3390 						   op1, op2, op3);
3391 	hbb->append_insn (insn);
3392       }
3393       return;
3394 
3395     case GIMPLE_BINARY_RHS:
3396       gen_hsa_binary_operation (opcode, dest, op1, op2, hbb);
3397       break;
3398 
3399     case GIMPLE_UNARY_RHS:
3400       gen_hsa_unary_operation (opcode, dest, op1, hbb);
3401       break;
3402     default:
3403       gcc_unreachable ();
3404     }
3405 }
3406 
3407 /* Generate HSA instructions for a given gimple condition statement COND.
3408    Instructions will be appended to HBB, which also needs to be the
3409    corresponding structure to the basic_block of COND.  */
3410 
3411 static void
gen_hsa_insns_for_cond_stmt(gimple * cond,hsa_bb * hbb)3412 gen_hsa_insns_for_cond_stmt (gimple *cond, hsa_bb *hbb)
3413 {
3414   hsa_op_reg *ctrl = new hsa_op_reg (BRIG_TYPE_B1);
3415   hsa_insn_cbr *cbr;
3416 
3417   gen_hsa_cmp_insn_from_gimple (gimple_cond_code (cond),
3418 				gimple_cond_lhs (cond),
3419 				gimple_cond_rhs (cond),
3420 				ctrl, hbb);
3421 
3422   cbr = new hsa_insn_cbr (ctrl);
3423   hbb->append_insn (cbr);
3424 }
3425 
3426 /* Maximum number of elements in a jump table for an HSA SBR instruction.  */
3427 
3428 #define HSA_MAXIMUM_SBR_LABELS	16
3429 
3430 /* Return lowest value of a switch S that is handled in a non-default
3431    label.  */
3432 
3433 static tree
get_switch_low(gswitch * s)3434 get_switch_low (gswitch *s)
3435 {
3436   unsigned labels = gimple_switch_num_labels (s);
3437   gcc_checking_assert (labels >= 1);
3438 
3439   return CASE_LOW (gimple_switch_label (s, 1));
3440 }
3441 
3442 /* Return highest value of a switch S that is handled in a non-default
3443    label.  */
3444 
3445 static tree
get_switch_high(gswitch * s)3446 get_switch_high (gswitch *s)
3447 {
3448   unsigned labels = gimple_switch_num_labels (s);
3449 
3450   /* Compare last label to maximum number of labels.  */
3451   tree label = gimple_switch_label (s, labels - 1);
3452   tree low = CASE_LOW (label);
3453   tree high = CASE_HIGH (label);
3454 
3455   return high != NULL_TREE ? high : low;
3456 }
3457 
3458 static tree
get_switch_size(gswitch * s)3459 get_switch_size (gswitch *s)
3460 {
3461   return int_const_binop (MINUS_EXPR, get_switch_high (s), get_switch_low (s));
3462 }
3463 
3464 /* Generate HSA instructions for a given gimple switch.
3465    Instructions will be appended to HBB.  */
3466 
3467 static void
gen_hsa_insns_for_switch_stmt(gswitch * s,hsa_bb * hbb)3468 gen_hsa_insns_for_switch_stmt (gswitch *s, hsa_bb *hbb)
3469 {
3470   gimple_stmt_iterator it = gsi_for_stmt (s);
3471   gsi_prev (&it);
3472 
3473   /* Create preambule that verifies that index - lowest_label >= 0.  */
3474   edge e = split_block (hbb->m_bb, gsi_stmt (it));
3475   e->flags &= ~EDGE_FALLTHRU;
3476   e->flags |= EDGE_TRUE_VALUE;
3477 
3478   tree index_tree = gimple_switch_index (s);
3479   tree lowest = get_switch_low (s);
3480   tree highest = get_switch_high (s);
3481 
3482   hsa_op_reg *index = hsa_cfun->reg_for_gimple_ssa (index_tree);
3483   index = as_a <hsa_op_reg *> (index->extend_int_to_32bit (hbb));
3484 
3485   hsa_op_reg *cmp1_reg = new hsa_op_reg (BRIG_TYPE_B1);
3486   hsa_op_immed *cmp1_immed = new hsa_op_immed (lowest, true);
3487   hbb->append_insn (new hsa_insn_cmp (BRIG_COMPARE_GE, cmp1_reg->m_type,
3488 				      cmp1_reg, index, cmp1_immed));
3489 
3490   hsa_op_reg *cmp2_reg = new hsa_op_reg (BRIG_TYPE_B1);
3491   hsa_op_immed *cmp2_immed = new hsa_op_immed (highest, true);
3492   hbb->append_insn (new hsa_insn_cmp (BRIG_COMPARE_LE, cmp2_reg->m_type,
3493 				      cmp2_reg, index, cmp2_immed));
3494 
3495   hsa_op_reg *cmp_reg = new hsa_op_reg (BRIG_TYPE_B1);
3496   hbb->append_insn (new hsa_insn_basic (3, BRIG_OPCODE_AND, cmp_reg->m_type,
3497 					cmp_reg, cmp1_reg, cmp2_reg));
3498 
3499   hbb->append_insn (new hsa_insn_cbr (cmp_reg));
3500 
3501   basic_block default_label_bb = gimple_switch_default_bb (cfun, s);
3502 
3503   if (!gimple_seq_empty_p (phi_nodes (default_label_bb)))
3504     {
3505       default_label_bb = split_edge (find_edge (e->dest, default_label_bb));
3506       hsa_init_new_bb (default_label_bb);
3507     }
3508 
3509   make_edge (e->src, default_label_bb, EDGE_FALSE_VALUE);
3510 
3511   hsa_cfun->m_modified_cfg = true;
3512 
3513   /* Basic block with the SBR instruction.  */
3514   hbb = hsa_init_new_bb (e->dest);
3515 
3516   hsa_op_reg *sub_index = new hsa_op_reg (index->m_type);
3517   hbb->append_insn (new hsa_insn_basic (3, BRIG_OPCODE_SUB, sub_index->m_type,
3518 					sub_index, index,
3519 					new hsa_op_immed (lowest, true)));
3520 
3521   hsa_op_base *tmp = sub_index->get_in_type (BRIG_TYPE_U64, hbb);
3522   sub_index = as_a <hsa_op_reg *> (tmp);
3523   unsigned labels = gimple_switch_num_labels (s);
3524   unsigned HOST_WIDE_INT size = tree_to_uhwi (get_switch_size (s));
3525 
3526   hsa_insn_sbr *sbr = new hsa_insn_sbr (sub_index, size + 1);
3527 
3528   /* Prepare array with default label destination.  */
3529   for (unsigned HOST_WIDE_INT i = 0; i <= size; i++)
3530     sbr->m_jump_table.safe_push (default_label_bb);
3531 
3532   /* Iterate all labels and fill up the jump table.  */
3533   for (unsigned i = 1; i < labels; i++)
3534     {
3535       tree label = gimple_switch_label (s, i);
3536       basic_block bb = label_to_block (cfun, CASE_LABEL (label));
3537 
3538       unsigned HOST_WIDE_INT sub_low
3539 	= tree_to_uhwi (int_const_binop (MINUS_EXPR, CASE_LOW (label), lowest));
3540 
3541       unsigned HOST_WIDE_INT sub_high = sub_low;
3542       tree high = CASE_HIGH (label);
3543       if (high != NULL)
3544 	sub_high = tree_to_uhwi (int_const_binop (MINUS_EXPR, high, lowest));
3545 
3546       for (unsigned HOST_WIDE_INT j = sub_low; j <= sub_high; j++)
3547 	sbr->m_jump_table[j] = bb;
3548     }
3549 
3550   hbb->append_insn (sbr);
3551 }
3552 
3553 /* Verify that the function DECL can be handled by HSA.  */
3554 
3555 static void
verify_function_arguments(tree decl)3556 verify_function_arguments (tree decl)
3557 {
3558   tree type = TREE_TYPE (decl);
3559   if (DECL_STATIC_CHAIN (decl))
3560     {
3561       HSA_SORRY_ATV (EXPR_LOCATION (decl),
3562 		     "HSA does not support nested functions: %qD", decl);
3563       return;
3564     }
3565   else if (!TYPE_ARG_TYPES (type) || stdarg_p (type))
3566     {
3567       HSA_SORRY_ATV (EXPR_LOCATION (decl),
3568 		     "HSA does not support functions with variadic arguments "
3569 		     "(or unknown return type): %qD", decl);
3570       return;
3571     }
3572 }
3573 
3574 /* Return BRIG type for FORMAL_ARG_TYPE.  If the formal argument type is NULL,
3575    return ACTUAL_ARG_TYPE.  */
3576 
3577 static BrigType16_t
get_format_argument_type(tree formal_arg_type,BrigType16_t actual_arg_type)3578 get_format_argument_type (tree formal_arg_type, BrigType16_t actual_arg_type)
3579 {
3580   if (formal_arg_type == NULL)
3581     return actual_arg_type;
3582 
3583   BrigType16_t decl_type
3584     = hsa_type_for_scalar_tree_type (formal_arg_type, false);
3585   return mem_type_for_type (decl_type);
3586 }
3587 
3588 /* Generate HSA instructions for a direct call instruction.
3589    Instructions will be appended to HBB, which also needs to be the
3590    corresponding structure to the basic_block of STMT.
3591    If ASSIGN_LHS is false, do not copy HSA function result argument into the
3592    corresponding HSA representation of the gimple statement LHS.  */
3593 
3594 static void
3595 gen_hsa_insns_for_direct_call (gimple *stmt, hsa_bb *hbb,
3596 			       bool assign_lhs = true)
3597 {
3598   tree decl = gimple_call_fndecl (stmt);
3599   verify_function_arguments (decl);
3600   if (hsa_seen_error ())
3601     return;
3602 
3603   hsa_insn_call *call_insn = new hsa_insn_call (decl);
3604   hsa_cfun->m_called_functions.safe_push (call_insn->m_called_function);
3605 
3606   /* Argument block start.  */
3607   hsa_insn_arg_block *arg_start
3608     = new hsa_insn_arg_block (BRIG_KIND_DIRECTIVE_ARG_BLOCK_START, call_insn);
3609   hbb->append_insn (arg_start);
3610 
3611   tree parm_type_chain = TYPE_ARG_TYPES (gimple_call_fntype (stmt));
3612 
3613   /* Preparation of arguments that will be passed to function.  */
3614   const unsigned args = gimple_call_num_args (stmt);
3615   for (unsigned i = 0; i < args; ++i)
3616     {
3617       tree parm = gimple_call_arg (stmt, (int)i);
3618       tree parm_decl_type = parm_type_chain != NULL_TREE
3619 	? TREE_VALUE (parm_type_chain) : NULL_TREE;
3620       hsa_op_address *addr;
3621 
3622       if (AGGREGATE_TYPE_P (TREE_TYPE (parm)))
3623 	{
3624 	  addr = gen_hsa_addr_for_arg (TREE_TYPE (parm), i);
3625 	  BrigAlignment8_t align;
3626 	  hsa_op_address *src = gen_hsa_addr_with_align (parm, hbb, &align);
3627 	  gen_hsa_memory_copy (hbb, addr, src,
3628 			       addr->m_symbol->total_byte_size (), align);
3629 	}
3630       else
3631 	{
3632 	  hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (parm, hbb);
3633 
3634 	  if (parm_decl_type != NULL && AGGREGATE_TYPE_P (parm_decl_type))
3635 	    {
3636 	      HSA_SORRY_AT (gimple_location (stmt),
3637 			    "support for HSA does not implement an aggregate "
3638 			    "formal argument in a function call, while actual "
3639 			    "argument is not an aggregate");
3640 	      return;
3641 	    }
3642 
3643 	  BrigType16_t formal_arg_type
3644 	    = get_format_argument_type (parm_decl_type, src->m_type);
3645 	  if (hsa_seen_error ())
3646 	    return;
3647 
3648 	  if (src->m_type != formal_arg_type)
3649 	    src = src->get_in_type (formal_arg_type, hbb);
3650 
3651 	  addr
3652 	    = gen_hsa_addr_for_arg (parm_decl_type != NULL_TREE ?
3653 				    parm_decl_type: TREE_TYPE (parm), i);
3654 	  hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, formal_arg_type,
3655 						src, addr);
3656 
3657 	  hbb->append_insn (mem);
3658 	}
3659 
3660       call_insn->m_input_args.safe_push (addr->m_symbol);
3661       if (parm_type_chain)
3662 	parm_type_chain = TREE_CHAIN (parm_type_chain);
3663     }
3664 
3665   call_insn->m_args_code_list = new hsa_op_code_list (args);
3666   hbb->append_insn (call_insn);
3667 
3668   tree result_type = TREE_TYPE (TREE_TYPE (decl));
3669 
3670   tree result = gimple_call_lhs (stmt);
3671   hsa_insn_mem *result_insn = NULL;
3672   if (!VOID_TYPE_P (result_type))
3673     {
3674       hsa_op_address *addr = gen_hsa_addr_for_arg (result_type, -1);
3675 
3676       /* Even if result of a function call is unused, we have to emit
3677 	 declaration for the result.  */
3678       if (result && assign_lhs)
3679 	{
3680 	  tree lhs_type = TREE_TYPE (result);
3681 
3682 	  if (hsa_seen_error ())
3683 	    return;
3684 
3685 	  if (AGGREGATE_TYPE_P (lhs_type))
3686 	    {
3687 	      BrigAlignment8_t align;
3688 	      hsa_op_address *result_addr
3689 		= gen_hsa_addr_with_align (result, hbb, &align);
3690 	      gen_hsa_memory_copy (hbb, result_addr, addr,
3691 				   addr->m_symbol->total_byte_size (), align);
3692 	    }
3693 	  else
3694 	    {
3695 	      BrigType16_t mtype
3696 		= mem_type_for_type (hsa_type_for_scalar_tree_type (lhs_type,
3697 								    false));
3698 
3699 	      hsa_op_reg *dst = hsa_cfun->reg_for_gimple_ssa (result);
3700 	      result_insn = new hsa_insn_mem (BRIG_OPCODE_LD, mtype, dst, addr);
3701 	      hbb->append_insn (result_insn);
3702 	    }
3703 	}
3704 
3705       call_insn->m_output_arg = addr->m_symbol;
3706       call_insn->m_result_code_list = new hsa_op_code_list (1);
3707     }
3708   else
3709     {
3710       if (result)
3711 	{
3712 	  HSA_SORRY_AT (gimple_location (stmt),
3713 			"support for HSA does not implement an assignment of "
3714 			"return value from a void function");
3715 	  return;
3716 	}
3717 
3718       call_insn->m_result_code_list = new hsa_op_code_list (0);
3719     }
3720 
3721   /* Argument block end.  */
3722   hsa_insn_arg_block *arg_end
3723     = new hsa_insn_arg_block (BRIG_KIND_DIRECTIVE_ARG_BLOCK_END, call_insn);
3724   hbb->append_insn (arg_end);
3725 }
3726 
3727 /* Generate HSA instructions for a direct call of an internal fn.
3728    Instructions will be appended to HBB, which also needs to be the
3729    corresponding structure to the basic_block of STMT.  */
3730 
3731 static void
gen_hsa_insns_for_call_of_internal_fn(gimple * stmt,hsa_bb * hbb)3732 gen_hsa_insns_for_call_of_internal_fn (gimple *stmt, hsa_bb *hbb)
3733 {
3734   tree lhs = gimple_call_lhs (stmt);
3735   if (!lhs)
3736     return;
3737 
3738   tree lhs_type = TREE_TYPE (lhs);
3739   tree rhs1 = gimple_call_arg (stmt, 0);
3740   tree rhs1_type = TREE_TYPE (rhs1);
3741   enum internal_fn fn = gimple_call_internal_fn (stmt);
3742   hsa_internal_fn *ifn
3743     = new hsa_internal_fn (fn, tree_to_uhwi (TYPE_SIZE (rhs1_type)));
3744   hsa_insn_call *call_insn = new hsa_insn_call (ifn);
3745 
3746   gcc_checking_assert (FLOAT_TYPE_P (rhs1_type));
3747 
3748   if (!hsa_emitted_internal_decls->find (call_insn->m_called_internal_fn))
3749     hsa_cfun->m_called_internal_fns.safe_push (call_insn->m_called_internal_fn);
3750 
3751   hsa_insn_arg_block *arg_start
3752     = new hsa_insn_arg_block (BRIG_KIND_DIRECTIVE_ARG_BLOCK_START, call_insn);
3753   hbb->append_insn (arg_start);
3754 
3755   unsigned num_args = gimple_call_num_args (stmt);
3756 
3757   /* Function arguments.  */
3758   for (unsigned i = 0; i < num_args; i++)
3759     {
3760       tree parm = gimple_call_arg (stmt, (int)i);
3761       hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (parm, hbb);
3762 
3763       hsa_op_address *addr = gen_hsa_addr_for_arg (TREE_TYPE (parm), i);
3764       hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, src->m_type,
3765 					    src, addr);
3766 
3767       call_insn->m_input_args.safe_push (addr->m_symbol);
3768       hbb->append_insn (mem);
3769     }
3770 
3771   call_insn->m_args_code_list = new hsa_op_code_list (num_args);
3772   hbb->append_insn (call_insn);
3773 
3774   /* Assign returned value.  */
3775   hsa_op_address *addr = gen_hsa_addr_for_arg (lhs_type, -1);
3776 
3777   call_insn->m_output_arg = addr->m_symbol;
3778   call_insn->m_result_code_list = new hsa_op_code_list (1);
3779 
3780   /* Argument block end.  */
3781   hsa_insn_arg_block *arg_end
3782     = new hsa_insn_arg_block (BRIG_KIND_DIRECTIVE_ARG_BLOCK_END, call_insn);
3783   hbb->append_insn (arg_end);
3784 }
3785 
3786 /* Generate HSA instructions for a return value instruction.
3787    Instructions will be appended to HBB, which also needs to be the
3788    corresponding structure to the basic_block of STMT.  */
3789 
3790 static void
gen_hsa_insns_for_return(greturn * stmt,hsa_bb * hbb)3791 gen_hsa_insns_for_return (greturn *stmt, hsa_bb *hbb)
3792 {
3793   tree retval = gimple_return_retval (stmt);
3794   if (retval)
3795     {
3796       hsa_op_address *addr = new hsa_op_address (hsa_cfun->m_output_arg);
3797 
3798       if (AGGREGATE_TYPE_P (TREE_TYPE (retval)))
3799 	{
3800 	  BrigAlignment8_t align;
3801 	  hsa_op_address *retval_addr = gen_hsa_addr_with_align (retval, hbb,
3802 								 &align);
3803 	  gen_hsa_memory_copy (hbb, addr, retval_addr,
3804 			       hsa_cfun->m_output_arg->total_byte_size (),
3805 			       align);
3806 	}
3807       else
3808 	{
3809 	  BrigType16_t t = hsa_type_for_scalar_tree_type (TREE_TYPE (retval),
3810 							  false);
3811 	  BrigType16_t mtype = mem_type_for_type (t);
3812 
3813 	  /* Store of return value.  */
3814 	  hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (retval, hbb);
3815 	  src = src->get_in_type (mtype, hbb);
3816 	  hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, mtype, src,
3817 						addr);
3818 	  hbb->append_insn (mem);
3819 	}
3820     }
3821 
3822   /* HSAIL return instruction emission.  */
3823   hsa_insn_basic *ret = new hsa_insn_basic (0, BRIG_OPCODE_RET);
3824   hbb->append_insn (ret);
3825 }
3826 
3827 /* Set OP_INDEX-th operand of the instruction to DEST, as the DEST
3828    can have a different type, conversion instructions are possibly
3829    appended to HBB.  */
3830 
3831 void
set_output_in_type(hsa_op_reg * dest,unsigned op_index,hsa_bb * hbb)3832 hsa_insn_basic::set_output_in_type (hsa_op_reg *dest, unsigned op_index,
3833 				    hsa_bb *hbb)
3834 {
3835   gcc_checking_assert (op_output_p (op_index));
3836 
3837   if (dest->m_type == m_type)
3838     {
3839       set_op (op_index, dest);
3840       return;
3841     }
3842 
3843   hsa_insn_basic *insn;
3844   hsa_op_reg *tmp;
3845   if (hsa_needs_cvt (dest->m_type, m_type))
3846     {
3847       tmp = new hsa_op_reg (m_type);
3848       insn = new hsa_insn_cvt (dest, tmp);
3849     }
3850   else if (hsa_type_bit_size (dest->m_type) == hsa_type_bit_size (m_type))
3851     {
3852       /* When output, HSA registers do not really have types, only sizes, so if
3853 	 the sizes match, we can use the register directly.  */
3854       set_op (op_index, dest);
3855       return;
3856     }
3857   else
3858     {
3859       tmp = new hsa_op_reg (m_type);
3860       insn = new hsa_insn_basic (2, BRIG_OPCODE_MOV, dest->m_type,
3861 				 dest, tmp->get_in_type (dest->m_type, hbb));
3862       hsa_fixup_mov_insn_type (insn);
3863     }
3864   set_op (op_index, tmp);
3865   hbb->append_insn (insn);
3866 }
3867 
3868 /* Generate instruction OPCODE to query a property of HSA grid along the
3869    given DIMENSION.  Store result into DEST and append the instruction to
3870    HBB.  */
3871 
3872 static void
query_hsa_grid_dim(hsa_op_reg * dest,int opcode,hsa_op_immed * dimension,hsa_bb * hbb)3873 query_hsa_grid_dim (hsa_op_reg *dest, int opcode, hsa_op_immed *dimension,
3874 		    hsa_bb *hbb)
3875 {
3876   hsa_insn_basic *insn = new hsa_insn_basic (2, opcode, BRIG_TYPE_U32, NULL,
3877 					     dimension);
3878   hbb->append_insn (insn);
3879   insn->set_output_in_type (dest, 0, hbb);
3880 }
3881 
3882 /* Generate instruction OPCODE to query a property of HSA grid along the given
3883    dimension which is an immediate in first argument of STMT.  Store result
3884    into the register corresponding to LHS of STMT and append the instruction to
3885    HBB.  */
3886 
3887 static void
query_hsa_grid_dim(gimple * stmt,int opcode,hsa_bb * hbb)3888 query_hsa_grid_dim (gimple *stmt, int opcode, hsa_bb *hbb)
3889 {
3890   tree lhs = gimple_call_lhs (dyn_cast <gcall *> (stmt));
3891   if (lhs == NULL_TREE)
3892     return;
3893 
3894   tree arg = gimple_call_arg (stmt, 0);
3895   unsigned HOST_WIDE_INT dim = 5;
3896   if (tree_fits_uhwi_p (arg))
3897     dim = tree_to_uhwi (arg);
3898   if (dim > 2)
3899     {
3900       HSA_SORRY_AT (gimple_location (stmt),
3901 		    "HSA grid query dimension must be immediate constant 0, 1 "
3902 		    "or 2");
3903       return;
3904     }
3905 
3906   hsa_op_immed *hdim = new hsa_op_immed (dim, (BrigKind16_t) BRIG_TYPE_U32);
3907   hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
3908   query_hsa_grid_dim (dest, opcode, hdim, hbb);
3909 }
3910 
3911 /* Generate instruction OPCODE to query a property of HSA grid that is
3912    independent of any dimension.  Store result into the register corresponding
3913    to LHS of STMT and append the instruction to HBB.  */
3914 
3915 static void
query_hsa_grid_nodim(gimple * stmt,BrigOpcode16_t opcode,hsa_bb * hbb)3916 query_hsa_grid_nodim (gimple *stmt, BrigOpcode16_t opcode, hsa_bb *hbb)
3917 {
3918   tree lhs = gimple_call_lhs (dyn_cast <gcall *> (stmt));
3919   if (lhs == NULL_TREE)
3920     return;
3921   hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
3922   BrigType16_t brig_type = hsa_unsigned_type_for_type (dest->m_type);
3923   hsa_insn_basic *insn = new hsa_insn_basic (1, opcode, brig_type, dest);
3924   hbb->append_insn (insn);
3925 }
3926 
3927 /* Emit instructions that set hsa_num_threads according to provided VALUE.
3928    Instructions are appended to basic block HBB.  */
3929 
3930 static void
gen_set_num_threads(tree value,hsa_bb * hbb)3931 gen_set_num_threads (tree value, hsa_bb *hbb)
3932 {
3933   hbb->append_insn (new hsa_insn_comment ("omp_set_num_threads"));
3934   hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (value, hbb);
3935 
3936   src = src->get_in_type (hsa_num_threads->m_type, hbb);
3937   hsa_op_address *addr = new hsa_op_address (hsa_num_threads);
3938 
3939   hsa_insn_basic *basic
3940     = new hsa_insn_mem (BRIG_OPCODE_ST, hsa_num_threads->m_type, src, addr);
3941   hbb->append_insn (basic);
3942 }
3943 
3944 /* Return byte offset of a FIELD_NAME in GOMP_hsa_kernel_dispatch which
3945    is defined in plugin-hsa.c.  */
3946 
3947 static HOST_WIDE_INT
get_hsa_kernel_dispatch_offset(const char * field_name)3948 get_hsa_kernel_dispatch_offset (const char *field_name)
3949 {
3950   tree *hsa_kernel_dispatch_type = hsa_get_kernel_dispatch_type ();
3951   if (*hsa_kernel_dispatch_type == NULL)
3952     {
3953       /* Collection of information needed for a dispatch of a kernel from a
3954 	 kernel.  Keep in sync with libgomp's plugin-hsa.c.  */
3955 
3956       *hsa_kernel_dispatch_type = make_node (RECORD_TYPE);
3957       tree id_f1 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3958 			       get_identifier ("queue"), ptr_type_node);
3959       DECL_CHAIN (id_f1) = NULL_TREE;
3960       tree id_f2 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3961 			       get_identifier ("omp_data_memory"),
3962 			       ptr_type_node);
3963       DECL_CHAIN (id_f2) = id_f1;
3964       tree id_f3 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3965 			       get_identifier ("kernarg_address"),
3966 			       ptr_type_node);
3967       DECL_CHAIN (id_f3) = id_f2;
3968       tree id_f4 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3969 			       get_identifier ("object"),
3970 			       uint64_type_node);
3971       DECL_CHAIN (id_f4) = id_f3;
3972       tree id_f5 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3973 			       get_identifier ("signal"),
3974 			       uint64_type_node);
3975       DECL_CHAIN (id_f5) = id_f4;
3976       tree id_f6 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3977 			       get_identifier ("private_segment_size"),
3978 			       uint32_type_node);
3979       DECL_CHAIN (id_f6) = id_f5;
3980       tree id_f7 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3981 			       get_identifier ("group_segment_size"),
3982 			       uint32_type_node);
3983       DECL_CHAIN (id_f7) = id_f6;
3984       tree id_f8 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3985 			       get_identifier ("kernel_dispatch_count"),
3986 			       uint64_type_node);
3987       DECL_CHAIN (id_f8) = id_f7;
3988       tree id_f9 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3989 			       get_identifier ("debug"),
3990 			       uint64_type_node);
3991       DECL_CHAIN (id_f9) = id_f8;
3992       tree id_f10 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3993 				get_identifier ("omp_level"),
3994 				uint64_type_node);
3995       DECL_CHAIN (id_f10) = id_f9;
3996       tree id_f11 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3997 				get_identifier ("children_dispatches"),
3998 				ptr_type_node);
3999       DECL_CHAIN (id_f11) = id_f10;
4000       tree id_f12 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
4001 			       get_identifier ("omp_num_threads"),
4002 			       uint32_type_node);
4003       DECL_CHAIN (id_f12) = id_f11;
4004 
4005 
4006       finish_builtin_struct (*hsa_kernel_dispatch_type, "__hsa_kernel_dispatch",
4007 			     id_f12, NULL_TREE);
4008       TYPE_ARTIFICIAL (*hsa_kernel_dispatch_type) = 1;
4009     }
4010 
4011   for (tree chain = TYPE_FIELDS (*hsa_kernel_dispatch_type);
4012        chain != NULL_TREE; chain = TREE_CHAIN (chain))
4013     if (id_equal (DECL_NAME (chain), field_name))
4014       return int_byte_position (chain);
4015 
4016   gcc_unreachable ();
4017 }
4018 
4019 /* Return an HSA register that will contain number of threads for
4020    a future dispatched kernel.  Instructions are added to HBB.  */
4021 
4022 static hsa_op_reg *
gen_num_threads_for_dispatch(hsa_bb * hbb)4023 gen_num_threads_for_dispatch (hsa_bb *hbb)
4024 {
4025   /* Step 1) Assign to number of threads:
4026      MIN (HSA_DEFAULT_NUM_THREADS, hsa_num_threads).  */
4027   hsa_op_reg *threads = new hsa_op_reg (hsa_num_threads->m_type);
4028   hsa_op_address *addr = new hsa_op_address (hsa_num_threads);
4029 
4030   hbb->append_insn (new hsa_insn_mem (BRIG_OPCODE_LD, threads->m_type,
4031 				      threads, addr));
4032 
4033   hsa_op_immed *limit = new hsa_op_immed (HSA_DEFAULT_NUM_THREADS,
4034 					  BRIG_TYPE_U32);
4035   hsa_op_reg *r = new hsa_op_reg (BRIG_TYPE_B1);
4036   hsa_insn_cmp * cmp
4037     = new hsa_insn_cmp (BRIG_COMPARE_LT, r->m_type, r, threads, limit);
4038   hbb->append_insn (cmp);
4039 
4040   BrigType16_t btype = hsa_bittype_for_type (threads->m_type);
4041   hsa_op_reg *tmp = new hsa_op_reg (threads->m_type);
4042 
4043   hbb->append_insn (new hsa_insn_basic (4, BRIG_OPCODE_CMOV, btype, tmp, r,
4044 					threads, limit));
4045 
4046   /* Step 2) If the number is equal to zero,
4047      return shadow->omp_num_threads.  */
4048   hsa_op_reg *shadow_reg_ptr = hsa_cfun->get_shadow_reg ();
4049 
4050   hsa_op_reg *shadow_thread_count = new hsa_op_reg (BRIG_TYPE_U32);
4051   addr
4052     = new hsa_op_address (shadow_reg_ptr,
4053 			  get_hsa_kernel_dispatch_offset ("omp_num_threads"));
4054   hsa_insn_basic *basic
4055     = new hsa_insn_mem (BRIG_OPCODE_LD, shadow_thread_count->m_type,
4056 			shadow_thread_count, addr);
4057   hbb->append_insn (basic);
4058 
4059   hsa_op_reg *tmp2 = new hsa_op_reg (threads->m_type);
4060   r = new hsa_op_reg (BRIG_TYPE_B1);
4061   hsa_op_immed *imm = new hsa_op_immed (0, shadow_thread_count->m_type);
4062   hbb->append_insn (new hsa_insn_cmp (BRIG_COMPARE_EQ, r->m_type, r, tmp, imm));
4063   hbb->append_insn (new hsa_insn_basic (4, BRIG_OPCODE_CMOV, btype, tmp2, r,
4064 					shadow_thread_count, tmp));
4065 
4066   hsa_op_base *dest = tmp2->get_in_type (BRIG_TYPE_U16, hbb);
4067 
4068   return as_a <hsa_op_reg *> (dest);
4069 }
4070 
4071 /* Build OPCODE query for all three hsa dimensions, multiply them and store the
4072    result into DEST.  */
4073 
4074 static void
multiply_grid_dim_characteristics(hsa_op_reg * dest,int opcode,hsa_bb * hbb)4075 multiply_grid_dim_characteristics (hsa_op_reg *dest, int opcode, hsa_bb *hbb)
4076 {
4077   hsa_op_reg *dimx = new hsa_op_reg (BRIG_TYPE_U32);
4078   query_hsa_grid_dim (dimx, opcode,
4079 		      new hsa_op_immed (0, (BrigKind16_t) BRIG_TYPE_U32), hbb);
4080   hsa_op_reg *dimy = new hsa_op_reg (BRIG_TYPE_U32);
4081   query_hsa_grid_dim (dimy, opcode,
4082 		      new hsa_op_immed (1, (BrigKind16_t) BRIG_TYPE_U32), hbb);
4083   hsa_op_reg *dimz = new hsa_op_reg (BRIG_TYPE_U32);
4084   query_hsa_grid_dim (dimz, opcode,
4085 		      new hsa_op_immed (2, (BrigKind16_t) BRIG_TYPE_U32), hbb);
4086   hsa_op_reg *tmp = new hsa_op_reg (dest->m_type);
4087   gen_hsa_binary_operation (BRIG_OPCODE_MUL, tmp,
4088 			    dimx->get_in_type (dest->m_type, hbb),
4089 			    dimy->get_in_type (dest->m_type, hbb), hbb);
4090   gen_hsa_binary_operation (BRIG_OPCODE_MUL, dest, tmp,
4091 			    dimz->get_in_type (dest->m_type, hbb), hbb);
4092 }
4093 
4094 /* Emit instructions that assign number of threads to lhs of gimple STMT.
4095    Instructions are appended to basic block HBB.  */
4096 
4097 static void
gen_get_num_threads(gimple * stmt,hsa_bb * hbb)4098 gen_get_num_threads (gimple *stmt, hsa_bb *hbb)
4099 {
4100   if (gimple_call_lhs (stmt) == NULL_TREE)
4101     return;
4102 
4103   hbb->append_insn (new hsa_insn_comment ("omp_get_num_threads"));
4104   tree lhs = gimple_call_lhs (stmt);
4105   hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4106   multiply_grid_dim_characteristics (dest, BRIG_OPCODE_CURRENTWORKGROUPSIZE,
4107 				     hbb);
4108 }
4109 
4110 /* Emit instructions that assign number of teams to lhs of gimple STMT.
4111    Instructions are appended to basic block HBB.  */
4112 
4113 static void
gen_get_num_teams(gimple * stmt,hsa_bb * hbb)4114 gen_get_num_teams (gimple *stmt, hsa_bb *hbb)
4115 {
4116   if (gimple_call_lhs (stmt) == NULL_TREE)
4117     return;
4118 
4119   hbb->append_insn (new hsa_insn_comment ("omp_get_num_teams"));
4120   tree lhs = gimple_call_lhs (stmt);
4121   hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4122   multiply_grid_dim_characteristics (dest, BRIG_OPCODE_GRIDGROUPS, hbb);
4123 }
4124 
4125 /* Emit instructions that assign a team number to lhs of gimple STMT.
4126    Instructions are appended to basic block HBB.  */
4127 
4128 static void
gen_get_team_num(gimple * stmt,hsa_bb * hbb)4129 gen_get_team_num (gimple *stmt, hsa_bb *hbb)
4130 {
4131   if (gimple_call_lhs (stmt) == NULL_TREE)
4132     return;
4133 
4134   hbb->append_insn (new hsa_insn_comment ("omp_get_team_num"));
4135   tree lhs = gimple_call_lhs (stmt);
4136   hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4137 
4138   hsa_op_reg *gnum_x = new hsa_op_reg (BRIG_TYPE_U32);
4139   query_hsa_grid_dim (gnum_x, BRIG_OPCODE_GRIDGROUPS,
4140 		      new hsa_op_immed (0, (BrigKind16_t) BRIG_TYPE_U32), hbb);
4141   hsa_op_reg *gnum_y = new hsa_op_reg (BRIG_TYPE_U32);
4142   query_hsa_grid_dim (gnum_y, BRIG_OPCODE_GRIDGROUPS,
4143 		      new hsa_op_immed (1, (BrigKind16_t) BRIG_TYPE_U32), hbb);
4144 
4145   hsa_op_reg *gno_z = new hsa_op_reg (BRIG_TYPE_U32);
4146   query_hsa_grid_dim (gno_z, BRIG_OPCODE_WORKGROUPID,
4147 		      new hsa_op_immed (2, (BrigKind16_t) BRIG_TYPE_U32), hbb);
4148 
4149   hsa_op_reg *tmp1 = new hsa_op_reg (dest->m_type);
4150   gen_hsa_binary_operation (BRIG_OPCODE_MUL, tmp1,
4151 			    gnum_x->get_in_type (dest->m_type, hbb),
4152 			    gnum_y->get_in_type (dest->m_type, hbb), hbb);
4153   hsa_op_reg *tmp2 = new hsa_op_reg (dest->m_type);
4154   gen_hsa_binary_operation (BRIG_OPCODE_MUL, tmp2, tmp1,
4155 			    gno_z->get_in_type (dest->m_type, hbb), hbb);
4156 
4157   hsa_op_reg *gno_y = new hsa_op_reg (BRIG_TYPE_U32);
4158   query_hsa_grid_dim (gno_y, BRIG_OPCODE_WORKGROUPID,
4159 		      new hsa_op_immed (1, (BrigKind16_t) BRIG_TYPE_U32), hbb);
4160   hsa_op_reg *tmp3 = new hsa_op_reg (dest->m_type);
4161   gen_hsa_binary_operation (BRIG_OPCODE_MUL, tmp3,
4162 			    gnum_x->get_in_type (dest->m_type, hbb),
4163 			    gno_y->get_in_type (dest->m_type, hbb), hbb);
4164   hsa_op_reg *tmp4 = new hsa_op_reg (dest->m_type);
4165   gen_hsa_binary_operation (BRIG_OPCODE_ADD, tmp4, tmp3, tmp2, hbb);
4166   hsa_op_reg *gno_x = new hsa_op_reg (BRIG_TYPE_U32);
4167   query_hsa_grid_dim (gno_x, BRIG_OPCODE_WORKGROUPID,
4168 		      new hsa_op_immed (0, (BrigKind16_t) BRIG_TYPE_U32), hbb);
4169   gen_hsa_binary_operation (BRIG_OPCODE_ADD, dest, tmp4,
4170 			    gno_x->get_in_type (dest->m_type, hbb), hbb);
4171 }
4172 
4173 /* Emit instructions that get levels-var ICV to lhs of gimple STMT.
4174    Instructions are appended to basic block HBB.  */
4175 
4176 static void
gen_get_level(gimple * stmt,hsa_bb * hbb)4177 gen_get_level (gimple *stmt, hsa_bb *hbb)
4178 {
4179   if (gimple_call_lhs (stmt) == NULL_TREE)
4180     return;
4181 
4182   hbb->append_insn (new hsa_insn_comment ("omp_get_level"));
4183 
4184   tree lhs = gimple_call_lhs (stmt);
4185   hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4186 
4187   hsa_op_reg *shadow_reg_ptr = hsa_cfun->get_shadow_reg ();
4188   if (shadow_reg_ptr == NULL)
4189     {
4190       HSA_SORRY_AT (gimple_location (stmt),
4191 		    "support for HSA does not implement %<omp_get_level%> "
4192 		    "called from a function not being inlined within a kernel");
4193       return;
4194     }
4195 
4196   hsa_op_address *addr
4197     = new hsa_op_address (shadow_reg_ptr,
4198 			  get_hsa_kernel_dispatch_offset ("omp_level"));
4199 
4200   hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, BRIG_TYPE_U64,
4201 					(hsa_op_base *) NULL, addr);
4202   hbb->append_insn (mem);
4203   mem->set_output_in_type (dest, 0, hbb);
4204 }
4205 
4206 /* Emit instruction that implement omp_get_max_threads of gimple STMT.  */
4207 
4208 static void
gen_get_max_threads(gimple * stmt,hsa_bb * hbb)4209 gen_get_max_threads (gimple *stmt, hsa_bb *hbb)
4210 {
4211   tree lhs = gimple_call_lhs (stmt);
4212   if (!lhs)
4213     return;
4214 
4215   hbb->append_insn (new hsa_insn_comment ("omp_get_max_threads"));
4216 
4217   hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4218   hsa_op_with_type *num_theads_reg = gen_num_threads_for_dispatch (hbb)
4219     ->get_in_type (dest->m_type, hbb);
4220   hsa_build_append_simple_mov (dest, num_theads_reg, hbb);
4221 }
4222 
4223 /* Emit instructions that implement alloca builtin gimple STMT.
4224    Instructions are appended to basic block HBB.  */
4225 
4226 static void
gen_hsa_alloca(gcall * call,hsa_bb * hbb)4227 gen_hsa_alloca (gcall *call, hsa_bb *hbb)
4228 {
4229   tree lhs = gimple_call_lhs (call);
4230   if (lhs == NULL_TREE)
4231     return;
4232 
4233   tree fndecl = gimple_call_fndecl (call);
4234   built_in_function fn = DECL_FUNCTION_CODE (fndecl);
4235 
4236   gcc_checking_assert (ALLOCA_FUNCTION_CODE_P (fn));
4237 
4238   unsigned bit_alignment = 0;
4239 
4240   if (fn != BUILT_IN_ALLOCA)
4241     {
4242       tree alignment_tree = gimple_call_arg (call, 1);
4243       if (TREE_CODE (alignment_tree) != INTEGER_CST)
4244 	{
4245 	  HSA_SORRY_ATV (gimple_location (call),
4246 			 "support for HSA does not implement "
4247 			 "%qD with a non-constant alignment %E",
4248 			 fndecl, alignment_tree);
4249 	}
4250 
4251       bit_alignment = tree_to_uhwi (alignment_tree);
4252     }
4253 
4254   tree rhs1 = gimple_call_arg (call, 0);
4255   hsa_op_with_type *size = hsa_reg_or_immed_for_gimple_op (rhs1, hbb)
4256     ->get_in_type (BRIG_TYPE_U32, hbb);
4257   hsa_op_with_type *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4258 
4259   hsa_op_reg *tmp
4260     = new hsa_op_reg (hsa_get_segment_addr_type (BRIG_SEGMENT_PRIVATE));
4261   hsa_insn_alloca *a = new hsa_insn_alloca (tmp, size, bit_alignment);
4262   hbb->append_insn (a);
4263 
4264   hsa_insn_seg *seg
4265     = new hsa_insn_seg (BRIG_OPCODE_STOF,
4266 			hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT),
4267 			tmp->m_type, BRIG_SEGMENT_PRIVATE, dest, tmp);
4268   hbb->append_insn (seg);
4269 }
4270 
4271 /* Emit instructions that implement clrsb builtin STMT:
4272    Returns the number of leading redundant sign bits in x, i.e. the number
4273    of bits following the most significant bit that are identical to it.
4274    There are no special cases for 0 or other values.
4275    Instructions are appended to basic block HBB.  */
4276 
4277 static void
gen_hsa_clrsb(gcall * call,hsa_bb * hbb)4278 gen_hsa_clrsb (gcall *call, hsa_bb *hbb)
4279 {
4280   tree lhs = gimple_call_lhs (call);
4281   if (lhs == NULL_TREE)
4282     return;
4283 
4284   hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4285   tree rhs1 = gimple_call_arg (call, 0);
4286   hsa_op_with_type *arg = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
4287   arg->extend_int_to_32bit (hbb);
4288   BrigType16_t bittype = hsa_bittype_for_type (arg->m_type);
4289   unsigned bitsize = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (rhs1)));
4290 
4291   /* FIRSTBIT instruction is defined just for 32 and 64-bits wide integers.  */
4292   gcc_checking_assert (bitsize == 32 || bitsize == 64);
4293 
4294   /* Set true to MOST_SIG if the most significant bit is set to one.  */
4295   hsa_op_immed *c = new hsa_op_immed (1ul << (bitsize - 1),
4296 				      hsa_uint_for_bitsize (bitsize));
4297 
4298   hsa_op_reg *and_reg = new hsa_op_reg (bittype);
4299   gen_hsa_binary_operation (BRIG_OPCODE_AND, and_reg, arg, c, hbb);
4300 
4301   hsa_op_reg *most_sign = new hsa_op_reg (BRIG_TYPE_B1);
4302   hsa_insn_cmp *cmp
4303     = new hsa_insn_cmp (BRIG_COMPARE_EQ, most_sign->m_type, most_sign,
4304 			and_reg, c);
4305   hbb->append_insn (cmp);
4306 
4307   /* If the most significant bit is one, negate the input.  Otherwise
4308      shift the input value to left by one bit.  */
4309   hsa_op_reg *arg_neg = new hsa_op_reg (arg->m_type);
4310   gen_hsa_unary_operation (BRIG_OPCODE_NEG, arg_neg, arg, hbb);
4311 
4312   hsa_op_reg *shifted_arg = new hsa_op_reg (arg->m_type);
4313   gen_hsa_binary_operation (BRIG_OPCODE_SHL, shifted_arg, arg,
4314 			    new hsa_op_immed (1, BRIG_TYPE_U64), hbb);
4315 
4316   /* Assign the value that can be used for FIRSTBIT instruction according
4317      to the most significant bit.  */
4318   hsa_op_reg *tmp = new hsa_op_reg (bittype);
4319   hsa_insn_basic *cmov
4320     = new hsa_insn_basic (4, BRIG_OPCODE_CMOV, bittype, tmp, most_sign,
4321 			  arg_neg, shifted_arg);
4322   hbb->append_insn (cmov);
4323 
4324   hsa_op_reg *leading_bits = new hsa_op_reg (BRIG_TYPE_S32);
4325   gen_hsa_unary_operation (BRIG_OPCODE_FIRSTBIT, leading_bits,
4326 			   tmp->get_in_type (hsa_uint_for_bitsize (bitsize),
4327 					     hbb), hbb);
4328 
4329   /* Set flag if the input value is equal to zero.  */
4330   hsa_op_reg *is_zero = new hsa_op_reg (BRIG_TYPE_B1);
4331   cmp = new hsa_insn_cmp (BRIG_COMPARE_EQ, is_zero->m_type, is_zero, arg,
4332 			  new hsa_op_immed (0, arg->m_type));
4333   hbb->append_insn (cmp);
4334 
4335   /* Return the number of leading bits,
4336      or (bitsize - 1) if the input value is zero.  */
4337   cmov = new hsa_insn_basic (4, BRIG_OPCODE_CMOV, BRIG_TYPE_B32, NULL, is_zero,
4338 			     new hsa_op_immed (bitsize - 1, BRIG_TYPE_U32),
4339 			     leading_bits->get_in_type (BRIG_TYPE_B32, hbb));
4340   hbb->append_insn (cmov);
4341   cmov->set_output_in_type (dest, 0, hbb);
4342 }
4343 
4344 /* Emit instructions that implement ffs builtin STMT:
4345    Returns one plus the index of the least significant 1-bit of x,
4346    or if x is zero, returns zero.
4347    Instructions are appended to basic block HBB.  */
4348 
4349 static void
gen_hsa_ffs(gcall * call,hsa_bb * hbb)4350 gen_hsa_ffs (gcall *call, hsa_bb *hbb)
4351 {
4352   tree lhs = gimple_call_lhs (call);
4353   if (lhs == NULL_TREE)
4354     return;
4355 
4356   hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4357 
4358   tree rhs1 = gimple_call_arg (call, 0);
4359   hsa_op_with_type *arg = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
4360   arg = arg->extend_int_to_32bit (hbb);
4361 
4362   hsa_op_reg *tmp = new hsa_op_reg (BRIG_TYPE_U32);
4363   hsa_insn_srctype *insn = new hsa_insn_srctype (2, BRIG_OPCODE_LASTBIT,
4364 						 tmp->m_type, arg->m_type,
4365 						 tmp, arg);
4366   hbb->append_insn (insn);
4367 
4368   hsa_insn_basic *addition
4369     = new hsa_insn_basic (3, BRIG_OPCODE_ADD, tmp->m_type, NULL, tmp,
4370 			  new hsa_op_immed (1, tmp->m_type));
4371   hbb->append_insn (addition);
4372   addition->set_output_in_type (dest, 0, hbb);
4373 }
4374 
4375 static void
gen_hsa_popcount_to_dest(hsa_op_reg * dest,hsa_op_with_type * arg,hsa_bb * hbb)4376 gen_hsa_popcount_to_dest (hsa_op_reg *dest, hsa_op_with_type *arg, hsa_bb *hbb)
4377 {
4378   gcc_checking_assert (hsa_type_integer_p (arg->m_type));
4379 
4380   if (hsa_type_bit_size (arg->m_type) < 32)
4381     arg = arg->get_in_type (BRIG_TYPE_B32, hbb);
4382 
4383   BrigType16_t srctype = hsa_bittype_for_type (arg->m_type);
4384   if (!hsa_btype_p (arg->m_type))
4385     arg = arg->get_in_type (srctype, hbb);
4386 
4387   hsa_insn_srctype *popcount
4388     = new hsa_insn_srctype (2, BRIG_OPCODE_POPCOUNT, BRIG_TYPE_U32,
4389 			    srctype, NULL, arg);
4390   hbb->append_insn (popcount);
4391   popcount->set_output_in_type (dest, 0, hbb);
4392 }
4393 
4394 /* Emit instructions that implement parity builtin STMT:
4395    Returns the parity of x, i.e. the number of 1-bits in x modulo 2.
4396    Instructions are appended to basic block HBB.  */
4397 
4398 static void
gen_hsa_parity(gcall * call,hsa_bb * hbb)4399 gen_hsa_parity (gcall *call, hsa_bb *hbb)
4400 {
4401   tree lhs = gimple_call_lhs (call);
4402   if (lhs == NULL_TREE)
4403     return;
4404 
4405   hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4406   tree rhs1 = gimple_call_arg (call, 0);
4407   hsa_op_with_type *arg = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
4408 
4409   hsa_op_reg *popcount = new hsa_op_reg (BRIG_TYPE_U32);
4410   gen_hsa_popcount_to_dest (popcount, arg, hbb);
4411 
4412   hsa_insn_basic *insn
4413     = new hsa_insn_basic (3, BRIG_OPCODE_REM, popcount->m_type, NULL, popcount,
4414 			  new hsa_op_immed (2, popcount->m_type));
4415   hbb->append_insn (insn);
4416   insn->set_output_in_type (dest, 0, hbb);
4417 }
4418 
4419 /* Emit instructions that implement popcount builtin STMT.
4420    Instructions are appended to basic block HBB.  */
4421 
4422 static void
gen_hsa_popcount(gcall * call,hsa_bb * hbb)4423 gen_hsa_popcount (gcall *call, hsa_bb *hbb)
4424 {
4425   tree lhs = gimple_call_lhs (call);
4426   if (lhs == NULL_TREE)
4427     return;
4428 
4429   hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4430   tree rhs1 = gimple_call_arg (call, 0);
4431   hsa_op_with_type *arg = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
4432 
4433   gen_hsa_popcount_to_dest (dest, arg, hbb);
4434 }
4435 
4436 /* Emit instructions that implement DIVMOD builtin STMT.
4437    Instructions are appended to basic block HBB.  */
4438 
4439 static void
gen_hsa_divmod(gcall * call,hsa_bb * hbb)4440 gen_hsa_divmod (gcall *call, hsa_bb *hbb)
4441 {
4442   tree lhs = gimple_call_lhs (call);
4443   if (lhs == NULL_TREE)
4444     return;
4445 
4446   tree rhs0 = gimple_call_arg (call, 0);
4447   tree rhs1 = gimple_call_arg (call, 1);
4448 
4449   hsa_op_with_type *arg0 = hsa_reg_or_immed_for_gimple_op (rhs0, hbb);
4450   arg0 = arg0->extend_int_to_32bit (hbb);
4451   hsa_op_with_type *arg1 = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
4452   arg1 = arg1->extend_int_to_32bit (hbb);
4453 
4454   hsa_op_reg *dest0 = new hsa_op_reg (arg0->m_type);
4455   hsa_op_reg *dest1 = new hsa_op_reg (arg1->m_type);
4456 
4457   hsa_insn_basic *insn = new hsa_insn_basic (3, BRIG_OPCODE_DIV, dest0->m_type,
4458 					     dest0, arg0, arg1);
4459   hbb->append_insn (insn);
4460   insn = new hsa_insn_basic (3, BRIG_OPCODE_REM, dest1->m_type, dest1, arg0,
4461 			     arg1);
4462   hbb->append_insn (insn);
4463 
4464   hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4465   BrigType16_t dst_type = hsa_extend_inttype_to_32bit (dest->m_type);
4466   BrigType16_t src_type = hsa_bittype_for_type (dest0->m_type);
4467 
4468   insn = new hsa_insn_packed (3, BRIG_OPCODE_COMBINE, dst_type,
4469 			      src_type, NULL, dest0, dest1);
4470   hbb->append_insn (insn);
4471   insn->set_output_in_type (dest, 0, hbb);
4472 }
4473 
4474 /* Emit instructions that implement FMA, FMS, FNMA or FNMS call STMT.
4475    Instructions are appended to basic block HBB.  NEGATE1 is true for
4476    FNMA and FNMS.  NEGATE3 is true for FMS and FNMS.  */
4477 
4478 static void
gen_hsa_fma(gcall * call,hsa_bb * hbb,bool negate1,bool negate3)4479 gen_hsa_fma (gcall *call, hsa_bb *hbb, bool negate1, bool negate3)
4480 {
4481   tree lhs = gimple_call_lhs (call);
4482   if (lhs == NULL_TREE)
4483     return;
4484 
4485   tree rhs1 = gimple_call_arg (call, 0);
4486   tree rhs2 = gimple_call_arg (call, 1);
4487   tree rhs3 = gimple_call_arg (call, 2);
4488 
4489   hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4490   hsa_op_with_type *op1 = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
4491   hsa_op_with_type *op2 = hsa_reg_or_immed_for_gimple_op (rhs2, hbb);
4492   hsa_op_with_type *op3 = hsa_reg_or_immed_for_gimple_op (rhs3, hbb);
4493 
4494   if (negate1)
4495     {
4496       hsa_op_reg *tmp = new hsa_op_reg (dest->m_type);
4497       gen_hsa_unary_operation (BRIG_OPCODE_NEG, tmp, op1, hbb);
4498       op1 = tmp;
4499     }
4500 
4501   /* There is a native HSA instruction for scalar FMAs but not for vector
4502      ones.  */
4503   if (TREE_CODE (TREE_TYPE (lhs)) == VECTOR_TYPE)
4504     {
4505       hsa_op_reg *tmp = new hsa_op_reg (dest->m_type);
4506       gen_hsa_binary_operation (BRIG_OPCODE_MUL, tmp, op1, op2, hbb);
4507       gen_hsa_binary_operation (negate3 ? BRIG_OPCODE_SUB : BRIG_OPCODE_ADD,
4508 				dest, tmp, op3, hbb);
4509     }
4510   else
4511     {
4512       if (negate3)
4513 	{
4514 	  hsa_op_reg *tmp = new hsa_op_reg (dest->m_type);
4515 	  gen_hsa_unary_operation (BRIG_OPCODE_NEG, tmp, op3, hbb);
4516 	  op3 = tmp;
4517 	}
4518       hsa_insn_basic *insn = new hsa_insn_basic (4, BRIG_OPCODE_MAD,
4519 						 dest->m_type, dest,
4520 						 op1, op2, op3);
4521       hbb->append_insn (insn);
4522     }
4523 }
4524 
4525 /* Set VALUE to a shadow kernel debug argument and append a new instruction
4526    to HBB basic block.  */
4527 
4528 static void
set_debug_value(hsa_bb * hbb,hsa_op_with_type * value)4529 set_debug_value (hsa_bb *hbb, hsa_op_with_type *value)
4530 {
4531   hsa_op_reg *shadow_reg_ptr = hsa_cfun->get_shadow_reg ();
4532   if (shadow_reg_ptr == NULL)
4533     return;
4534 
4535   hsa_op_address *addr
4536     = new hsa_op_address (shadow_reg_ptr,
4537 			  get_hsa_kernel_dispatch_offset ("debug"));
4538   hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, BRIG_TYPE_U64, value,
4539 					addr);
4540   hbb->append_insn (mem);
4541 }
4542 
4543 void
generate(gimple * stmt,hsa_bb * hbb)4544 omp_simple_builtin::generate (gimple *stmt, hsa_bb *hbb)
4545 {
4546   if (m_sorry)
4547     {
4548       if (m_warning_message)
4549 	HSA_SORRY_AT (gimple_location (stmt), m_warning_message);
4550       else
4551 	HSA_SORRY_ATV (gimple_location (stmt),
4552 		       "support for HSA does not implement calls to %qs",
4553 		       m_name);
4554     }
4555   else if (m_warning_message != NULL)
4556     warning_at (gimple_location (stmt), OPT_Whsa, m_warning_message);
4557 
4558   if (m_return_value != NULL)
4559     {
4560       tree lhs = gimple_call_lhs (stmt);
4561       if (!lhs)
4562 	return;
4563 
4564       hbb->append_insn (new hsa_insn_comment (m_name));
4565 
4566       hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4567       hsa_op_with_type *op = m_return_value->get_in_type (dest->m_type, hbb);
4568       hsa_build_append_simple_mov (dest, op, hbb);
4569     }
4570 }
4571 
4572 /* If STMT is a call of a known library function, generate code to perform
4573    it and return true.  */
4574 
4575 static bool
gen_hsa_insns_for_known_library_call(gimple * stmt,hsa_bb * hbb)4576 gen_hsa_insns_for_known_library_call (gimple *stmt, hsa_bb *hbb)
4577 {
4578   bool handled = false;
4579   const char *name = hsa_get_declaration_name (gimple_call_fndecl (stmt));
4580 
4581   char *copy = NULL;
4582   size_t len = strlen (name);
4583   if (len > 0 && name[len - 1] == '_')
4584     {
4585       copy = XNEWVEC (char, len + 1);
4586       strcpy (copy, name);
4587       copy[len - 1] = '\0';
4588       name = copy;
4589     }
4590 
4591   /* Handle omp_* routines.  */
4592   if (strstr (name, "omp_") == name)
4593     {
4594       hsa_init_simple_builtins ();
4595       omp_simple_builtin *builtin = omp_simple_builtins->get (name);
4596       if (builtin)
4597 	{
4598 	  builtin->generate (stmt, hbb);
4599 	  return true;
4600 	}
4601 
4602       handled = true;
4603       if (strcmp (name, "omp_set_num_threads") == 0)
4604 	gen_set_num_threads (gimple_call_arg (stmt, 0), hbb);
4605       else if (strcmp (name, "omp_get_thread_num") == 0)
4606 	{
4607 	  hbb->append_insn (new hsa_insn_comment (name));
4608 	  query_hsa_grid_nodim (stmt, BRIG_OPCODE_WORKITEMFLATABSID, hbb);
4609 	}
4610       else if (strcmp (name, "omp_get_num_threads") == 0)
4611 	{
4612 	  hbb->append_insn (new hsa_insn_comment (name));
4613 	  gen_get_num_threads (stmt, hbb);
4614 	}
4615       else if (strcmp (name, "omp_get_num_teams") == 0)
4616 	gen_get_num_teams (stmt, hbb);
4617       else if (strcmp (name, "omp_get_team_num") == 0)
4618 	gen_get_team_num (stmt, hbb);
4619       else if (strcmp (name, "omp_get_level") == 0)
4620 	gen_get_level (stmt, hbb);
4621       else if (strcmp (name, "omp_get_active_level") == 0)
4622 	gen_get_level (stmt, hbb);
4623       else if (strcmp (name, "omp_in_parallel") == 0)
4624 	gen_get_level (stmt, hbb);
4625       else if (strcmp (name, "omp_get_max_threads") == 0)
4626 	gen_get_max_threads (stmt, hbb);
4627       else
4628 	handled = false;
4629 
4630       if (handled)
4631 	{
4632 	  if (copy)
4633 	    free (copy);
4634 	  return true;
4635 	}
4636     }
4637 
4638   if (strcmp (name, "__hsa_set_debug_value") == 0)
4639     {
4640       handled = true;
4641       if (hsa_cfun->has_shadow_reg_p ())
4642 	{
4643 	  tree rhs1 = gimple_call_arg (stmt, 0);
4644 	  hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
4645 
4646 	  src = src->get_in_type (BRIG_TYPE_U64, hbb);
4647 	  set_debug_value (hbb, src);
4648 	}
4649     }
4650 
4651   if (copy)
4652     free (copy);
4653   return handled;
4654 }
4655 
4656 /* Helper functions to create a single unary HSA operations out of calls to
4657    builtins.  OPCODE is the HSA operation to be generated.  STMT is a gimple
4658    call to a builtin.  HBB is the HSA BB to which the instruction should be
4659    added.  Note that nothing will be created if STMT does not have a LHS.  */
4660 
4661 static void
gen_hsa_unaryop_for_builtin(BrigOpcode opcode,gimple * stmt,hsa_bb * hbb)4662 gen_hsa_unaryop_for_builtin (BrigOpcode opcode, gimple *stmt, hsa_bb *hbb)
4663 {
4664   tree lhs = gimple_call_lhs (stmt);
4665   if (!lhs)
4666     return;
4667   hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4668   hsa_op_with_type *op
4669     = hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 0), hbb);
4670   gen_hsa_unary_operation (opcode, dest, op, hbb);
4671 }
4672 
4673 /* Helper functions to create a call to standard library if LHS of the
4674    STMT is used.  HBB is the HSA BB to which the instruction should be
4675    added.  */
4676 
4677 static void
gen_hsa_unaryop_builtin_call(gimple * stmt,hsa_bb * hbb)4678 gen_hsa_unaryop_builtin_call (gimple *stmt, hsa_bb *hbb)
4679 {
4680   tree lhs = gimple_call_lhs (stmt);
4681   if (!lhs)
4682     return;
4683 
4684   if (gimple_call_internal_p (stmt))
4685     gen_hsa_insns_for_call_of_internal_fn (stmt, hbb);
4686   else
4687     gen_hsa_insns_for_direct_call (stmt, hbb);
4688 }
4689 
4690 /* Helper functions to create a single unary HSA operations out of calls to
4691    builtins (if unsafe math optimizations are enable). Otherwise, create
4692    a call to standard library function.
4693    OPCODE is the HSA operation to be generated.  STMT is a gimple
4694    call to a builtin.  HBB is the HSA BB to which the instruction should be
4695    added.  Note that nothing will be created if STMT does not have a LHS.  */
4696 
4697 static void
gen_hsa_unaryop_or_call_for_builtin(BrigOpcode opcode,gimple * stmt,hsa_bb * hbb)4698 gen_hsa_unaryop_or_call_for_builtin (BrigOpcode opcode, gimple *stmt,
4699 				     hsa_bb *hbb)
4700 {
4701   if (flag_unsafe_math_optimizations)
4702     gen_hsa_unaryop_for_builtin (opcode, stmt, hbb);
4703   else
4704     gen_hsa_unaryop_builtin_call (stmt, hbb);
4705 }
4706 
4707 /* Generate HSA address corresponding to a value VAL (as opposed to a memory
4708    reference tree), for example an SSA_NAME or an ADDR_EXPR.  HBB is the HSA BB
4709    to which the instruction should be added.  */
4710 
4711 static hsa_op_address *
get_address_from_value(tree val,hsa_bb * hbb)4712 get_address_from_value (tree val, hsa_bb *hbb)
4713 {
4714   switch (TREE_CODE (val))
4715     {
4716     case SSA_NAME:
4717       {
4718 	BrigType16_t addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
4719 	hsa_op_base *reg
4720 	  = hsa_cfun->reg_for_gimple_ssa (val)->get_in_type (addrtype, hbb);
4721 	return new hsa_op_address (NULL, as_a <hsa_op_reg *> (reg), 0);
4722       }
4723     case ADDR_EXPR:
4724       return gen_hsa_addr (TREE_OPERAND (val, 0), hbb);
4725 
4726     case INTEGER_CST:
4727       if (tree_fits_shwi_p (val))
4728 	return new hsa_op_address (NULL, NULL, tree_to_shwi (val));
4729       /* fall-through */
4730 
4731     default:
4732       HSA_SORRY_ATV (EXPR_LOCATION (val),
4733 		     "support for HSA does not implement memory access to %E",
4734 		     val);
4735       return new hsa_op_address (NULL, NULL, 0);
4736     }
4737 }
4738 
4739 /* Expand assignment of a result of a string BUILTIN to DST.
4740    Size of the operation is N bytes, where instructions
4741    will be append to HBB.  */
4742 
4743 static void
expand_lhs_of_string_op(gimple * stmt,unsigned HOST_WIDE_INT n,hsa_bb * hbb,enum built_in_function builtin)4744 expand_lhs_of_string_op (gimple *stmt,
4745 			 unsigned HOST_WIDE_INT n, hsa_bb *hbb,
4746 			 enum built_in_function builtin)
4747 {
4748   /* If LHS is expected, we need to emit a PHI instruction.  */
4749   tree lhs = gimple_call_lhs (stmt);
4750   if (!lhs)
4751     return;
4752 
4753   hsa_op_reg *lhs_reg = hsa_cfun->reg_for_gimple_ssa (lhs);
4754 
4755   hsa_op_with_type *dst_reg
4756     = hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 0), hbb);
4757   hsa_op_with_type *tmp;
4758 
4759   switch (builtin)
4760     {
4761     case BUILT_IN_MEMPCPY:
4762       {
4763 	tmp = new hsa_op_reg (dst_reg->m_type);
4764 	hsa_insn_basic *add
4765 	  = new hsa_insn_basic (3, BRIG_OPCODE_ADD, tmp->m_type,
4766 				tmp, dst_reg,
4767 				new hsa_op_immed (n, dst_reg->m_type));
4768 	hbb->append_insn (add);
4769 	break;
4770       }
4771     case BUILT_IN_MEMCPY:
4772     case BUILT_IN_MEMSET:
4773       tmp = dst_reg;
4774       break;
4775     default:
4776       gcc_unreachable ();
4777     }
4778 
4779   hbb->append_insn (new hsa_insn_basic (2, BRIG_OPCODE_MOV, lhs_reg->m_type,
4780 					lhs_reg, tmp));
4781 }
4782 
4783 #define HSA_MEMORY_BUILTINS_LIMIT     128
4784 
4785 /* Expand a string builtin (from a gimple STMT) in a way that
4786    according to MISALIGNED_FLAG we process either direct emission
4787    (a bunch of memory load and store instructions), or we emit a function call
4788    of a library function (for instance 'memcpy'). Actually, a basic block
4789    for direct emission is just prepared, where caller is responsible
4790    for emission of corresponding instructions.
4791    All instruction are appended to HBB.  */
4792 
4793 hsa_bb *
expand_string_operation_builtin(gimple * stmt,hsa_bb * hbb,hsa_op_reg * misaligned_flag)4794 expand_string_operation_builtin (gimple *stmt, hsa_bb *hbb,
4795 				 hsa_op_reg *misaligned_flag)
4796 {
4797   edge e = split_block (hbb->m_bb, stmt);
4798   basic_block condition_bb = e->src;
4799   hbb->append_insn (new hsa_insn_cbr (misaligned_flag));
4800 
4801   /* Prepare the control flow.  */
4802   edge condition_edge = EDGE_SUCC (condition_bb, 0);
4803   basic_block call_bb = split_edge (condition_edge);
4804 
4805   basic_block expanded_bb = split_edge (EDGE_SUCC (call_bb, 0));
4806   basic_block cont_bb = EDGE_SUCC (expanded_bb, 0)->dest;
4807   basic_block merge_bb = split_edge (EDGE_PRED (cont_bb, 0));
4808 
4809   condition_edge->flags &= ~EDGE_FALLTHRU;
4810   condition_edge->flags |= EDGE_TRUE_VALUE;
4811   make_edge (condition_bb, expanded_bb, EDGE_FALSE_VALUE);
4812 
4813   redirect_edge_succ (EDGE_SUCC (call_bb, 0), merge_bb);
4814 
4815   hsa_cfun->m_modified_cfg = true;
4816 
4817   hsa_init_new_bb (expanded_bb);
4818 
4819   /* Slow path: function call.  */
4820   gen_hsa_insns_for_direct_call (stmt, hsa_init_new_bb (call_bb), false);
4821 
4822   return hsa_bb_for_bb (expanded_bb);
4823 }
4824 
4825 /* Expand a memory copy BUILTIN (BUILT_IN_MEMCPY, BUILT_IN_MEMPCPY) from
4826    a gimple STMT and store all necessary instruction to HBB basic block.  */
4827 
4828 static void
expand_memory_copy(gimple * stmt,hsa_bb * hbb,enum built_in_function builtin)4829 expand_memory_copy (gimple *stmt, hsa_bb *hbb, enum built_in_function builtin)
4830 {
4831   tree byte_size = gimple_call_arg (stmt, 2);
4832 
4833   if (!tree_fits_uhwi_p (byte_size))
4834     {
4835       gen_hsa_insns_for_direct_call (stmt, hbb);
4836       return;
4837     }
4838 
4839   unsigned HOST_WIDE_INT n = tree_to_uhwi (byte_size);
4840 
4841   if (n > HSA_MEMORY_BUILTINS_LIMIT)
4842     {
4843       gen_hsa_insns_for_direct_call (stmt, hbb);
4844       return;
4845     }
4846 
4847   tree dst = gimple_call_arg (stmt, 0);
4848   tree src = gimple_call_arg (stmt, 1);
4849 
4850   hsa_op_address *dst_addr = get_address_from_value (dst, hbb);
4851   hsa_op_address *src_addr = get_address_from_value (src, hbb);
4852 
4853   /* As gen_hsa_memory_copy relies on memory alignment
4854      greater or equal to 8 bytes, we need to verify the alignment.  */
4855   BrigType16_t addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
4856   hsa_op_reg *src_addr_reg = new hsa_op_reg (addrtype);
4857   hsa_op_reg *dst_addr_reg = new hsa_op_reg (addrtype);
4858 
4859   convert_addr_to_flat_segment (src_addr, src_addr_reg, hbb);
4860   convert_addr_to_flat_segment (dst_addr, dst_addr_reg, hbb);
4861 
4862   /* Process BIT OR for source and destination addresses.  */
4863   hsa_op_reg *or_reg = new hsa_op_reg (addrtype);
4864   gen_hsa_binary_operation (BRIG_OPCODE_OR, or_reg, src_addr_reg,
4865 			    dst_addr_reg, hbb);
4866 
4867   /* Process BIT AND with 0x7 to identify the desired alignment
4868      of 8 bytes.  */
4869   hsa_op_reg *masked = new hsa_op_reg (addrtype);
4870 
4871   gen_hsa_binary_operation (BRIG_OPCODE_AND, masked, or_reg,
4872 			    new hsa_op_immed (7, addrtype), hbb);
4873 
4874   hsa_op_reg *misaligned = new hsa_op_reg (BRIG_TYPE_B1);
4875   hbb->append_insn (new hsa_insn_cmp (BRIG_COMPARE_NE, misaligned->m_type,
4876 				      misaligned, masked,
4877 				      new hsa_op_immed (0, masked->m_type)));
4878 
4879   hsa_bb *native_impl_bb
4880     = expand_string_operation_builtin (stmt, hbb, misaligned);
4881 
4882   gen_hsa_memory_copy (native_impl_bb, dst_addr, src_addr, n, BRIG_ALIGNMENT_8);
4883   hsa_bb *merge_bb
4884     = hsa_init_new_bb (EDGE_SUCC (native_impl_bb->m_bb, 0)->dest);
4885   expand_lhs_of_string_op (stmt, n, merge_bb, builtin);
4886 }
4887 
4888 
4889 /* Expand a memory set BUILTIN (BUILT_IN_MEMSET, BUILT_IN_BZERO) from
4890    a gimple STMT and store all necessary instruction to HBB basic block.
4891    The operation set N bytes with a CONSTANT value.  */
4892 
4893 static void
expand_memory_set(gimple * stmt,unsigned HOST_WIDE_INT n,unsigned HOST_WIDE_INT constant,hsa_bb * hbb,enum built_in_function builtin)4894 expand_memory_set (gimple *stmt, unsigned HOST_WIDE_INT n,
4895 		   unsigned HOST_WIDE_INT constant, hsa_bb *hbb,
4896 		   enum built_in_function builtin)
4897 {
4898   tree dst = gimple_call_arg (stmt, 0);
4899   hsa_op_address *dst_addr = get_address_from_value (dst, hbb);
4900 
4901   /* As gen_hsa_memory_set relies on memory alignment
4902      greater or equal to 8 bytes, we need to verify the alignment.  */
4903   BrigType16_t addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
4904   hsa_op_reg *dst_addr_reg = new hsa_op_reg (addrtype);
4905   convert_addr_to_flat_segment (dst_addr, dst_addr_reg, hbb);
4906 
4907   /* Process BIT AND with 0x7 to identify the desired alignment
4908      of 8 bytes.  */
4909   hsa_op_reg *masked = new hsa_op_reg (addrtype);
4910 
4911   gen_hsa_binary_operation (BRIG_OPCODE_AND, masked, dst_addr_reg,
4912 			    new hsa_op_immed (7, addrtype), hbb);
4913 
4914   hsa_op_reg *misaligned = new hsa_op_reg (BRIG_TYPE_B1);
4915   hbb->append_insn (new hsa_insn_cmp (BRIG_COMPARE_NE, misaligned->m_type,
4916 				      misaligned, masked,
4917 				      new hsa_op_immed (0, masked->m_type)));
4918 
4919   hsa_bb *native_impl_bb
4920     = expand_string_operation_builtin (stmt, hbb, misaligned);
4921 
4922   gen_hsa_memory_set (native_impl_bb, dst_addr, constant, n, BRIG_ALIGNMENT_8);
4923   hsa_bb *merge_bb
4924     = hsa_init_new_bb (EDGE_SUCC (native_impl_bb->m_bb, 0)->dest);
4925   expand_lhs_of_string_op (stmt, n, merge_bb, builtin);
4926 }
4927 
4928 /* Store into MEMORDER the memory order specified by tree T, which must be an
4929    integer constant representing a C++ memory order.  If it isn't, issue an HSA
4930    sorry message using LOC and return true, otherwise return false and store
4931    the name of the requested order to *MNAME.  */
4932 
4933 static bool
hsa_memorder_from_tree(tree t,BrigMemoryOrder * memorder,const char ** mname,location_t loc)4934 hsa_memorder_from_tree (tree t, BrigMemoryOrder *memorder, const char **mname,
4935 			location_t loc)
4936 {
4937   if (!tree_fits_uhwi_p (t))
4938     {
4939       HSA_SORRY_ATV (loc, "support for HSA does not implement memory model %E",
4940 		     t);
4941       return true;
4942     }
4943 
4944   unsigned HOST_WIDE_INT mm = tree_to_uhwi (t);
4945   switch (mm & MEMMODEL_BASE_MASK)
4946     {
4947     case MEMMODEL_RELAXED:
4948       *memorder = BRIG_MEMORY_ORDER_RELAXED;
4949       *mname = "relaxed";
4950       break;
4951     case MEMMODEL_CONSUME:
4952       /* HSA does not have an equivalent, but we can use the slightly stronger
4953 	 ACQUIRE.  */
4954       *memorder = BRIG_MEMORY_ORDER_SC_ACQUIRE;
4955       *mname = "consume";
4956       break;
4957     case MEMMODEL_ACQUIRE:
4958       *memorder = BRIG_MEMORY_ORDER_SC_ACQUIRE;
4959       *mname = "acquire";
4960       break;
4961     case MEMMODEL_RELEASE:
4962       *memorder = BRIG_MEMORY_ORDER_SC_RELEASE;
4963       *mname = "release";
4964       break;
4965     case MEMMODEL_ACQ_REL:
4966       *memorder = BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE;
4967       *mname = "acq_rel";
4968       break;
4969     case MEMMODEL_SEQ_CST:
4970       /* Callers implementing a simple load or store need to remove the release
4971 	 or acquire part respectively.  */
4972       *memorder = BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE;
4973       *mname = "seq_cst";
4974       break;
4975     default:
4976       {
4977 	HSA_SORRY_AT (loc, "support for HSA does not implement the specified "
4978 		      "memory model");
4979 	return true;
4980       }
4981     }
4982   return false;
4983 }
4984 
4985 /* Helper function to create an HSA atomic operation instruction out of calls
4986    to atomic builtins.  RET_ORIG is true if the built-in is the variant that
4987    return s the value before applying operation, and false if it should return
4988    the value after applying the operation (if it returns value at all).  ACODE
4989    is the atomic operation code, STMT is a gimple call to a builtin.  HBB is
4990    the HSA BB to which the instruction should be added.  If SIGNAL is true, the
4991    created operation will work on HSA signals rather than atomic variables.  */
4992 
4993 static void
gen_hsa_atomic_for_builtin(bool ret_orig,enum BrigAtomicOperation acode,gimple * stmt,hsa_bb * hbb,bool signal)4994 gen_hsa_atomic_for_builtin (bool ret_orig, enum BrigAtomicOperation acode,
4995 			    gimple *stmt, hsa_bb *hbb, bool signal)
4996 {
4997   tree lhs = gimple_call_lhs (stmt);
4998 
4999   tree type = TREE_TYPE (gimple_call_arg (stmt, 1));
5000   BrigType16_t hsa_type = hsa_type_for_scalar_tree_type (type, false);
5001   BrigType16_t mtype = mem_type_for_type (hsa_type);
5002   BrigMemoryOrder memorder;
5003   const char *mmname;
5004 
5005   if (hsa_memorder_from_tree (gimple_call_arg (stmt, 2), &memorder, &mmname,
5006 			      gimple_location (stmt)))
5007     return;
5008 
5009   /* Certain atomic insns must have Bx memory types.  */
5010   switch (acode)
5011     {
5012     case BRIG_ATOMIC_LD:
5013     case BRIG_ATOMIC_ST:
5014     case BRIG_ATOMIC_AND:
5015     case BRIG_ATOMIC_OR:
5016     case BRIG_ATOMIC_XOR:
5017     case BRIG_ATOMIC_EXCH:
5018       mtype = hsa_bittype_for_type (mtype);
5019       break;
5020     default:
5021       break;
5022     }
5023 
5024   hsa_op_reg *dest;
5025   int nops, opcode;
5026   if (lhs)
5027     {
5028       if (ret_orig)
5029 	dest = hsa_cfun->reg_for_gimple_ssa (lhs);
5030       else
5031 	dest = new hsa_op_reg (hsa_type);
5032       opcode = signal ? BRIG_OPCODE_SIGNAL : BRIG_OPCODE_ATOMIC;
5033       nops = 3;
5034     }
5035   else
5036     {
5037       dest = NULL;
5038       opcode = signal ? BRIG_OPCODE_SIGNALNORET : BRIG_OPCODE_ATOMICNORET;
5039       nops = 2;
5040     }
5041 
5042   if (acode == BRIG_ATOMIC_ST)
5043     {
5044       if (memorder == BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE)
5045 	memorder = BRIG_MEMORY_ORDER_SC_RELEASE;
5046 
5047       if (memorder != BRIG_MEMORY_ORDER_RELAXED
5048 	  && memorder != BRIG_MEMORY_ORDER_SC_RELEASE
5049 	  && memorder != BRIG_MEMORY_ORDER_NONE)
5050 	{
5051 	  HSA_SORRY_ATV (gimple_location (stmt),
5052 			 "support for HSA does not implement memory model for "
5053 			 "%<ATOMIC_ST%>: %s", mmname);
5054 	  return;
5055 	}
5056     }
5057 
5058   hsa_insn_basic *atominsn;
5059   hsa_op_base *tgt;
5060   if (signal)
5061     {
5062       atominsn = new hsa_insn_signal (nops, opcode, acode, mtype, memorder);
5063       tgt = hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 0), hbb);
5064     }
5065   else
5066     {
5067       atominsn = new hsa_insn_atomic (nops, opcode, acode, mtype, memorder);
5068       hsa_op_address *addr;
5069       addr = get_address_from_value (gimple_call_arg (stmt, 0), hbb);
5070       if (addr->m_symbol && addr->m_symbol->m_segment == BRIG_SEGMENT_PRIVATE)
5071 	{
5072 	  HSA_SORRY_AT (gimple_location (stmt),
5073 			"HSA does not implement atomic operations in private "
5074 			"segment");
5075 	  return;
5076 	}
5077       tgt = addr;
5078     }
5079 
5080   hsa_op_with_type *op
5081     = hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 1), hbb);
5082   if (lhs)
5083     {
5084       atominsn->set_op (0, dest);
5085       atominsn->set_op (1, tgt);
5086       atominsn->set_op (2, op);
5087     }
5088   else
5089     {
5090       atominsn->set_op (0, tgt);
5091       atominsn->set_op (1, op);
5092     }
5093 
5094   hbb->append_insn (atominsn);
5095 
5096   /* HSA does not natively support the variants that return the modified value,
5097      so re-do the operation again non-atomically if that is what was
5098      requested.  */
5099   if (lhs && !ret_orig)
5100     {
5101       int arith;
5102       switch (acode)
5103 	{
5104 	case BRIG_ATOMIC_ADD:
5105 	  arith = BRIG_OPCODE_ADD;
5106 	  break;
5107 	case BRIG_ATOMIC_AND:
5108 	  arith = BRIG_OPCODE_AND;
5109 	  break;
5110 	case BRIG_ATOMIC_OR:
5111 	  arith = BRIG_OPCODE_OR;
5112 	  break;
5113 	case BRIG_ATOMIC_SUB:
5114 	  arith = BRIG_OPCODE_SUB;
5115 	  break;
5116 	case BRIG_ATOMIC_XOR:
5117 	  arith = BRIG_OPCODE_XOR;
5118 	  break;
5119 	default:
5120 	  gcc_unreachable ();
5121 	}
5122       hsa_op_reg *real_dest = hsa_cfun->reg_for_gimple_ssa (lhs);
5123       gen_hsa_binary_operation (arith, real_dest, dest, op, hbb);
5124     }
5125 }
5126 
5127 /* Generate HSA instructions for an internal fn.
5128    Instructions will be appended to HBB, which also needs to be the
5129    corresponding structure to the basic_block of STMT.  */
5130 
5131 static void
gen_hsa_insn_for_internal_fn_call(gcall * stmt,hsa_bb * hbb)5132 gen_hsa_insn_for_internal_fn_call (gcall *stmt, hsa_bb *hbb)
5133 {
5134   gcc_checking_assert (gimple_call_internal_fn (stmt));
5135   internal_fn fn = gimple_call_internal_fn (stmt);
5136 
5137   bool is_float_type_p = false;
5138   if (gimple_call_lhs (stmt) != NULL
5139       && TREE_TYPE (gimple_call_lhs (stmt)) == float_type_node)
5140     is_float_type_p = true;
5141 
5142   switch (fn)
5143     {
5144     case IFN_CEIL:
5145       gen_hsa_unaryop_for_builtin (BRIG_OPCODE_CEIL, stmt, hbb);
5146       break;
5147 
5148     case IFN_FLOOR:
5149       gen_hsa_unaryop_for_builtin (BRIG_OPCODE_FLOOR, stmt, hbb);
5150       break;
5151 
5152     case IFN_RINT:
5153       gen_hsa_unaryop_for_builtin (BRIG_OPCODE_RINT, stmt, hbb);
5154       break;
5155 
5156     case IFN_SQRT:
5157       gen_hsa_unaryop_for_builtin (BRIG_OPCODE_SQRT, stmt, hbb);
5158       break;
5159 
5160     case IFN_RSQRT:
5161       gen_hsa_unaryop_for_builtin (BRIG_OPCODE_NRSQRT, stmt, hbb);
5162       break;
5163 
5164     case IFN_TRUNC:
5165       gen_hsa_unaryop_for_builtin (BRIG_OPCODE_TRUNC, stmt, hbb);
5166       break;
5167 
5168     case IFN_COS:
5169       {
5170 	if (is_float_type_p)
5171 	  gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NCOS, stmt, hbb);
5172 	else
5173 	  gen_hsa_unaryop_builtin_call (stmt, hbb);
5174 
5175 	break;
5176       }
5177     case IFN_EXP2:
5178       {
5179 	if (is_float_type_p)
5180 	  gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NEXP2, stmt, hbb);
5181 	else
5182 	  gen_hsa_unaryop_builtin_call (stmt, hbb);
5183 
5184 	break;
5185       }
5186 
5187     case IFN_LOG2:
5188       {
5189 	if (is_float_type_p)
5190 	  gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NLOG2, stmt, hbb);
5191 	else
5192 	  gen_hsa_unaryop_builtin_call (stmt, hbb);
5193 
5194 	break;
5195       }
5196 
5197     case IFN_SIN:
5198       {
5199 	if (is_float_type_p)
5200 	  gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NSIN, stmt, hbb);
5201 	else
5202 	  gen_hsa_unaryop_builtin_call (stmt, hbb);
5203 	break;
5204       }
5205 
5206     case IFN_CLRSB:
5207       gen_hsa_clrsb (stmt, hbb);
5208       break;
5209 
5210     case IFN_CLZ:
5211       gen_hsa_unaryop_for_builtin (BRIG_OPCODE_FIRSTBIT, stmt, hbb);
5212       break;
5213 
5214     case IFN_CTZ:
5215       gen_hsa_unaryop_for_builtin (BRIG_OPCODE_LASTBIT, stmt, hbb);
5216       break;
5217 
5218     case IFN_FFS:
5219       gen_hsa_ffs (stmt, hbb);
5220       break;
5221 
5222     case IFN_PARITY:
5223       gen_hsa_parity (stmt, hbb);
5224       break;
5225 
5226     case IFN_POPCOUNT:
5227       gen_hsa_popcount (stmt, hbb);
5228       break;
5229 
5230     case IFN_DIVMOD:
5231       gen_hsa_divmod (stmt, hbb);
5232       break;
5233 
5234     case IFN_ACOS:
5235     case IFN_ASIN:
5236     case IFN_ATAN:
5237     case IFN_EXP:
5238     case IFN_EXP10:
5239     case IFN_EXPM1:
5240     case IFN_LOG:
5241     case IFN_LOG10:
5242     case IFN_LOG1P:
5243     case IFN_LOGB:
5244     case IFN_SIGNIFICAND:
5245     case IFN_TAN:
5246     case IFN_NEARBYINT:
5247     case IFN_ROUND:
5248     case IFN_ATAN2:
5249     case IFN_COPYSIGN:
5250     case IFN_FMOD:
5251     case IFN_POW:
5252     case IFN_REMAINDER:
5253     case IFN_SCALB:
5254     case IFN_FMIN:
5255     case IFN_FMAX:
5256       gen_hsa_insns_for_call_of_internal_fn (stmt, hbb);
5257       break;
5258 
5259     case IFN_FMA:
5260       gen_hsa_fma (stmt, hbb, false, false);
5261       break;
5262 
5263     case IFN_FMS:
5264       gen_hsa_fma (stmt, hbb, false, true);
5265       break;
5266 
5267     case IFN_FNMA:
5268       gen_hsa_fma (stmt, hbb, true, false);
5269       break;
5270 
5271     case IFN_FNMS:
5272       gen_hsa_fma (stmt, hbb, true, true);
5273       break;
5274 
5275     default:
5276       HSA_SORRY_ATV (gimple_location (stmt),
5277 		     "support for HSA does not implement internal function: %s",
5278 		     internal_fn_name (fn));
5279       break;
5280     }
5281 }
5282 
5283 /* Generate HSA instructions for the given call statement STMT.  Instructions
5284    will be appended to HBB.  */
5285 
5286 static void
gen_hsa_insns_for_call(gimple * stmt,hsa_bb * hbb)5287 gen_hsa_insns_for_call (gimple *stmt, hsa_bb *hbb)
5288 {
5289   gcall *call = as_a <gcall *> (stmt);
5290   tree lhs = gimple_call_lhs (stmt);
5291   hsa_op_reg *dest;
5292 
5293   if (gimple_call_internal_p (stmt))
5294     {
5295       gen_hsa_insn_for_internal_fn_call (call, hbb);
5296       return;
5297     }
5298 
5299   if (!gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
5300     {
5301       tree function_decl = gimple_call_fndecl (stmt);
5302 
5303       if (function_decl == NULL_TREE)
5304 	{
5305 	  HSA_SORRY_AT (gimple_location (stmt),
5306 			"support for HSA does not implement indirect calls");
5307 	  return;
5308 	}
5309 
5310       /* Prefetch pass can create type-mismatching prefetch builtin calls which
5311 	 fail the gimple_call_builtin_p test above.  Handle them here.  */
5312       if (fndecl_built_in_p (function_decl, BUILT_IN_PREFETCH))
5313 	return;
5314 
5315       if (hsa_callable_function_p (function_decl))
5316 	gen_hsa_insns_for_direct_call (stmt, hbb);
5317       else if (!gen_hsa_insns_for_known_library_call (stmt, hbb))
5318 	HSA_SORRY_AT (gimple_location (stmt),
5319 		      "HSA supports only calls of functions marked with "
5320 		      "%<#pragma omp declare target%>");
5321       return;
5322     }
5323 
5324   tree fndecl = gimple_call_fndecl (stmt);
5325   enum built_in_function builtin = DECL_FUNCTION_CODE (fndecl);
5326   switch (builtin)
5327     {
5328     case BUILT_IN_FABS:
5329     case BUILT_IN_FABSF:
5330       gen_hsa_unaryop_for_builtin (BRIG_OPCODE_ABS, stmt, hbb);
5331       break;
5332 
5333     case BUILT_IN_CEIL:
5334     case BUILT_IN_CEILF:
5335       gen_hsa_unaryop_for_builtin (BRIG_OPCODE_CEIL, stmt, hbb);
5336       break;
5337 
5338     case BUILT_IN_FLOOR:
5339     case BUILT_IN_FLOORF:
5340       gen_hsa_unaryop_for_builtin (BRIG_OPCODE_FLOOR, stmt, hbb);
5341       break;
5342 
5343     case BUILT_IN_RINT:
5344     case BUILT_IN_RINTF:
5345       gen_hsa_unaryop_for_builtin (BRIG_OPCODE_RINT, stmt, hbb);
5346       break;
5347 
5348     case BUILT_IN_SQRT:
5349     case BUILT_IN_SQRTF:
5350       gen_hsa_unaryop_for_builtin (BRIG_OPCODE_SQRT, stmt, hbb);
5351       break;
5352 
5353     case BUILT_IN_TRUNC:
5354     case BUILT_IN_TRUNCF:
5355       gen_hsa_unaryop_for_builtin (BRIG_OPCODE_TRUNC, stmt, hbb);
5356       break;
5357 
5358     case BUILT_IN_COS:
5359     case BUILT_IN_SIN:
5360     case BUILT_IN_EXP2:
5361     case BUILT_IN_LOG2:
5362       /* HSAIL does not provide an instruction for double argument type.  */
5363       gen_hsa_unaryop_builtin_call (stmt, hbb);
5364       break;
5365 
5366     case BUILT_IN_COSF:
5367       gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NCOS, stmt, hbb);
5368       break;
5369 
5370     case BUILT_IN_EXP2F:
5371       gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NEXP2, stmt, hbb);
5372       break;
5373 
5374     case BUILT_IN_LOG2F:
5375       gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NLOG2, stmt, hbb);
5376       break;
5377 
5378     case BUILT_IN_SINF:
5379       gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NSIN, stmt, hbb);
5380       break;
5381 
5382     case BUILT_IN_CLRSB:
5383     case BUILT_IN_CLRSBL:
5384     case BUILT_IN_CLRSBLL:
5385       gen_hsa_clrsb (call, hbb);
5386       break;
5387 
5388     case BUILT_IN_CLZ:
5389     case BUILT_IN_CLZL:
5390     case BUILT_IN_CLZLL:
5391       gen_hsa_unaryop_for_builtin (BRIG_OPCODE_FIRSTBIT, stmt, hbb);
5392       break;
5393 
5394     case BUILT_IN_CTZ:
5395     case BUILT_IN_CTZL:
5396     case BUILT_IN_CTZLL:
5397       gen_hsa_unaryop_for_builtin (BRIG_OPCODE_LASTBIT, stmt, hbb);
5398       break;
5399 
5400     case BUILT_IN_FFS:
5401     case BUILT_IN_FFSL:
5402     case BUILT_IN_FFSLL:
5403       gen_hsa_ffs (call, hbb);
5404       break;
5405 
5406     case BUILT_IN_PARITY:
5407     case BUILT_IN_PARITYL:
5408     case BUILT_IN_PARITYLL:
5409       gen_hsa_parity (call, hbb);
5410       break;
5411 
5412     case BUILT_IN_POPCOUNT:
5413     case BUILT_IN_POPCOUNTL:
5414     case BUILT_IN_POPCOUNTLL:
5415       gen_hsa_popcount (call, hbb);
5416       break;
5417 
5418     case BUILT_IN_ATOMIC_LOAD_1:
5419     case BUILT_IN_ATOMIC_LOAD_2:
5420     case BUILT_IN_ATOMIC_LOAD_4:
5421     case BUILT_IN_ATOMIC_LOAD_8:
5422     case BUILT_IN_ATOMIC_LOAD_16:
5423       {
5424 	BrigType16_t mtype;
5425 	hsa_op_base *src;
5426 	src = get_address_from_value (gimple_call_arg (stmt, 0), hbb);
5427 
5428 	BrigMemoryOrder memorder;
5429 	const char *mmname;
5430 	if (hsa_memorder_from_tree (gimple_call_arg (stmt, 1), &memorder,
5431 				    &mmname, gimple_location (stmt)))
5432 	  return;
5433 
5434 	if (memorder == BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE)
5435 	  memorder = BRIG_MEMORY_ORDER_SC_ACQUIRE;
5436 
5437 	if (memorder != BRIG_MEMORY_ORDER_RELAXED
5438 	    && memorder != BRIG_MEMORY_ORDER_SC_ACQUIRE
5439 	    && memorder != BRIG_MEMORY_ORDER_NONE)
5440 	  {
5441 	    HSA_SORRY_ATV (gimple_location (stmt),
5442 			   "support for HSA does not implement "
5443 			   "memory model for atomic loads: %s", mmname);
5444 	    return;
5445 	  }
5446 
5447 	if (lhs)
5448 	  {
5449 	    BrigType16_t t = hsa_type_for_scalar_tree_type (TREE_TYPE (lhs),
5450 							    false);
5451 	    mtype = mem_type_for_type (t);
5452 	    mtype = hsa_bittype_for_type (mtype);
5453 	    dest = hsa_cfun->reg_for_gimple_ssa (lhs);
5454 	  }
5455 	else
5456 	  {
5457 	    mtype = BRIG_TYPE_B64;
5458 	    dest = new hsa_op_reg (mtype);
5459 	  }
5460 
5461 	hsa_insn_basic *atominsn;
5462 	atominsn = new hsa_insn_atomic (2, BRIG_OPCODE_ATOMIC, BRIG_ATOMIC_LD,
5463 					mtype, memorder, dest, src);
5464 
5465 	hbb->append_insn (atominsn);
5466 	break;
5467       }
5468 
5469     case BUILT_IN_ATOMIC_EXCHANGE_1:
5470     case BUILT_IN_ATOMIC_EXCHANGE_2:
5471     case BUILT_IN_ATOMIC_EXCHANGE_4:
5472     case BUILT_IN_ATOMIC_EXCHANGE_8:
5473     case BUILT_IN_ATOMIC_EXCHANGE_16:
5474       gen_hsa_atomic_for_builtin (true, BRIG_ATOMIC_EXCH, stmt, hbb, false);
5475       break;
5476       break;
5477 
5478     case BUILT_IN_ATOMIC_FETCH_ADD_1:
5479     case BUILT_IN_ATOMIC_FETCH_ADD_2:
5480     case BUILT_IN_ATOMIC_FETCH_ADD_4:
5481     case BUILT_IN_ATOMIC_FETCH_ADD_8:
5482     case BUILT_IN_ATOMIC_FETCH_ADD_16:
5483       gen_hsa_atomic_for_builtin (true, BRIG_ATOMIC_ADD, stmt, hbb, false);
5484       break;
5485       break;
5486 
5487     case BUILT_IN_ATOMIC_FETCH_SUB_1:
5488     case BUILT_IN_ATOMIC_FETCH_SUB_2:
5489     case BUILT_IN_ATOMIC_FETCH_SUB_4:
5490     case BUILT_IN_ATOMIC_FETCH_SUB_8:
5491     case BUILT_IN_ATOMIC_FETCH_SUB_16:
5492       gen_hsa_atomic_for_builtin (true, BRIG_ATOMIC_SUB, stmt, hbb, false);
5493       break;
5494       break;
5495 
5496     case BUILT_IN_ATOMIC_FETCH_AND_1:
5497     case BUILT_IN_ATOMIC_FETCH_AND_2:
5498     case BUILT_IN_ATOMIC_FETCH_AND_4:
5499     case BUILT_IN_ATOMIC_FETCH_AND_8:
5500     case BUILT_IN_ATOMIC_FETCH_AND_16:
5501       gen_hsa_atomic_for_builtin (true, BRIG_ATOMIC_AND, stmt, hbb, false);
5502       break;
5503       break;
5504 
5505     case BUILT_IN_ATOMIC_FETCH_XOR_1:
5506     case BUILT_IN_ATOMIC_FETCH_XOR_2:
5507     case BUILT_IN_ATOMIC_FETCH_XOR_4:
5508     case BUILT_IN_ATOMIC_FETCH_XOR_8:
5509     case BUILT_IN_ATOMIC_FETCH_XOR_16:
5510       gen_hsa_atomic_for_builtin (true, BRIG_ATOMIC_XOR, stmt, hbb, false);
5511       break;
5512       break;
5513 
5514     case BUILT_IN_ATOMIC_FETCH_OR_1:
5515     case BUILT_IN_ATOMIC_FETCH_OR_2:
5516     case BUILT_IN_ATOMIC_FETCH_OR_4:
5517     case BUILT_IN_ATOMIC_FETCH_OR_8:
5518     case BUILT_IN_ATOMIC_FETCH_OR_16:
5519       gen_hsa_atomic_for_builtin (true, BRIG_ATOMIC_OR, stmt, hbb, false);
5520       break;
5521       break;
5522 
5523     case BUILT_IN_ATOMIC_STORE_1:
5524     case BUILT_IN_ATOMIC_STORE_2:
5525     case BUILT_IN_ATOMIC_STORE_4:
5526     case BUILT_IN_ATOMIC_STORE_8:
5527     case BUILT_IN_ATOMIC_STORE_16:
5528       /* Since there cannot be any LHS, the first parameter is meaningless.  */
5529       gen_hsa_atomic_for_builtin (true, BRIG_ATOMIC_ST, stmt, hbb, false);
5530       break;
5531       break;
5532 
5533     case BUILT_IN_ATOMIC_ADD_FETCH_1:
5534     case BUILT_IN_ATOMIC_ADD_FETCH_2:
5535     case BUILT_IN_ATOMIC_ADD_FETCH_4:
5536     case BUILT_IN_ATOMIC_ADD_FETCH_8:
5537     case BUILT_IN_ATOMIC_ADD_FETCH_16:
5538       gen_hsa_atomic_for_builtin (false, BRIG_ATOMIC_ADD, stmt, hbb, false);
5539       break;
5540 
5541     case BUILT_IN_ATOMIC_SUB_FETCH_1:
5542     case BUILT_IN_ATOMIC_SUB_FETCH_2:
5543     case BUILT_IN_ATOMIC_SUB_FETCH_4:
5544     case BUILT_IN_ATOMIC_SUB_FETCH_8:
5545     case BUILT_IN_ATOMIC_SUB_FETCH_16:
5546       gen_hsa_atomic_for_builtin (false, BRIG_ATOMIC_SUB, stmt, hbb, false);
5547       break;
5548 
5549     case BUILT_IN_ATOMIC_AND_FETCH_1:
5550     case BUILT_IN_ATOMIC_AND_FETCH_2:
5551     case BUILT_IN_ATOMIC_AND_FETCH_4:
5552     case BUILT_IN_ATOMIC_AND_FETCH_8:
5553     case BUILT_IN_ATOMIC_AND_FETCH_16:
5554       gen_hsa_atomic_for_builtin (false, BRIG_ATOMIC_AND, stmt, hbb, false);
5555       break;
5556 
5557     case BUILT_IN_ATOMIC_XOR_FETCH_1:
5558     case BUILT_IN_ATOMIC_XOR_FETCH_2:
5559     case BUILT_IN_ATOMIC_XOR_FETCH_4:
5560     case BUILT_IN_ATOMIC_XOR_FETCH_8:
5561     case BUILT_IN_ATOMIC_XOR_FETCH_16:
5562       gen_hsa_atomic_for_builtin (false, BRIG_ATOMIC_XOR, stmt, hbb, false);
5563       break;
5564 
5565     case BUILT_IN_ATOMIC_OR_FETCH_1:
5566     case BUILT_IN_ATOMIC_OR_FETCH_2:
5567     case BUILT_IN_ATOMIC_OR_FETCH_4:
5568     case BUILT_IN_ATOMIC_OR_FETCH_8:
5569     case BUILT_IN_ATOMIC_OR_FETCH_16:
5570       gen_hsa_atomic_for_builtin (false, BRIG_ATOMIC_OR, stmt, hbb, false);
5571       break;
5572 
5573     case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_1:
5574     case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_2:
5575     case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_4:
5576     case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_8:
5577     case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_16:
5578       {
5579 	tree type = TREE_TYPE (gimple_call_arg (stmt, 1));
5580 	BrigType16_t atype
5581 	  = hsa_bittype_for_type (hsa_type_for_scalar_tree_type (type, false));
5582 	BrigMemoryOrder memorder = BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE;
5583 	hsa_insn_basic *atominsn;
5584 	hsa_op_base *tgt;
5585 	atominsn = new hsa_insn_atomic (4, BRIG_OPCODE_ATOMIC,
5586 					BRIG_ATOMIC_CAS, atype, memorder);
5587 	tgt = get_address_from_value (gimple_call_arg (stmt, 0), hbb);
5588 
5589 	if (lhs != NULL)
5590 	  dest = hsa_cfun->reg_for_gimple_ssa (lhs);
5591 	else
5592 	  dest = new hsa_op_reg (atype);
5593 
5594 	atominsn->set_op (0, dest);
5595 	atominsn->set_op (1, tgt);
5596 
5597 	hsa_op_with_type *op
5598 	  = hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 1), hbb);
5599 	atominsn->set_op (2, op);
5600 	op = hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 2), hbb);
5601 	atominsn->set_op (3, op);
5602 
5603 	hbb->append_insn (atominsn);
5604 	break;
5605       }
5606 
5607     case BUILT_IN_HSA_WORKGROUPID:
5608       query_hsa_grid_dim (stmt, BRIG_OPCODE_WORKGROUPID, hbb);
5609       break;
5610     case BUILT_IN_HSA_WORKITEMID:
5611       query_hsa_grid_dim (stmt, BRIG_OPCODE_WORKITEMID, hbb);
5612       break;
5613     case BUILT_IN_HSA_WORKITEMABSID:
5614       query_hsa_grid_dim (stmt, BRIG_OPCODE_WORKITEMABSID, hbb);
5615       break;
5616     case BUILT_IN_HSA_GRIDSIZE:
5617       query_hsa_grid_dim (stmt, BRIG_OPCODE_GRIDSIZE, hbb);
5618       break;
5619     case BUILT_IN_HSA_CURRENTWORKGROUPSIZE:
5620       query_hsa_grid_dim (stmt, BRIG_OPCODE_CURRENTWORKGROUPSIZE, hbb);
5621       break;
5622 
5623     case BUILT_IN_GOMP_BARRIER:
5624       hbb->append_insn (new hsa_insn_br (0, BRIG_OPCODE_BARRIER, BRIG_TYPE_NONE,
5625 					 BRIG_WIDTH_ALL));
5626       break;
5627     case BUILT_IN_GOMP_PARALLEL:
5628       HSA_SORRY_AT (gimple_location (stmt),
5629 		    "support for HSA does not implement non-gridified "
5630 		    "OpenMP parallel constructs");
5631       break;
5632 
5633     case BUILT_IN_OMP_GET_THREAD_NUM:
5634       {
5635 	query_hsa_grid_nodim (stmt, BRIG_OPCODE_WORKITEMFLATABSID, hbb);
5636 	break;
5637       }
5638 
5639     case BUILT_IN_OMP_GET_NUM_THREADS:
5640       {
5641 	gen_get_num_threads (stmt, hbb);
5642 	break;
5643       }
5644     case BUILT_IN_GOMP_TEAMS:
5645       {
5646 	gen_set_num_threads (gimple_call_arg (stmt, 1), hbb);
5647 	break;
5648       }
5649     case BUILT_IN_OMP_GET_NUM_TEAMS:
5650       {
5651 	gen_get_num_teams (stmt, hbb);
5652 	break;
5653       }
5654     case BUILT_IN_OMP_GET_TEAM_NUM:
5655       {
5656 	gen_get_team_num (stmt, hbb);
5657 	break;
5658       }
5659     case BUILT_IN_MEMCPY:
5660     case BUILT_IN_MEMPCPY:
5661       {
5662 	expand_memory_copy (stmt, hbb, builtin);
5663 	break;
5664       }
5665     case BUILT_IN_MEMSET:
5666       {
5667 	tree c = gimple_call_arg (stmt, 1);
5668 
5669 	if (TREE_CODE (c) != INTEGER_CST)
5670 	  {
5671 	    gen_hsa_insns_for_direct_call (stmt, hbb);
5672 	    return;
5673 	  }
5674 
5675 	tree byte_size = gimple_call_arg (stmt, 2);
5676 
5677 	if (!tree_fits_uhwi_p (byte_size))
5678 	  {
5679 	    gen_hsa_insns_for_direct_call (stmt, hbb);
5680 	    return;
5681 	  }
5682 
5683 	unsigned HOST_WIDE_INT n = tree_to_uhwi (byte_size);
5684 
5685 	if (n > HSA_MEMORY_BUILTINS_LIMIT)
5686 	  {
5687 	    gen_hsa_insns_for_direct_call (stmt, hbb);
5688 	    return;
5689 	  }
5690 
5691 	unsigned HOST_WIDE_INT constant
5692 	  = tree_to_uhwi (fold_convert (unsigned_char_type_node, c));
5693 
5694 	expand_memory_set (stmt, n, constant, hbb, builtin);
5695 
5696 	break;
5697       }
5698     case BUILT_IN_BZERO:
5699       {
5700 	tree byte_size = gimple_call_arg (stmt, 1);
5701 
5702 	if (!tree_fits_uhwi_p (byte_size))
5703 	  {
5704 	    gen_hsa_insns_for_direct_call (stmt, hbb);
5705 	    return;
5706 	  }
5707 
5708 	unsigned HOST_WIDE_INT n = tree_to_uhwi (byte_size);
5709 
5710 	if (n > HSA_MEMORY_BUILTINS_LIMIT)
5711 	  {
5712 	    gen_hsa_insns_for_direct_call (stmt, hbb);
5713 	    return;
5714 	  }
5715 
5716 	expand_memory_set (stmt, n, 0, hbb, builtin);
5717 
5718 	break;
5719       }
5720     CASE_BUILT_IN_ALLOCA:
5721       {
5722 	gen_hsa_alloca (call, hbb);
5723 	break;
5724       }
5725     case BUILT_IN_PREFETCH:
5726       break;
5727     default:
5728       {
5729 	tree name_tree = DECL_NAME (fndecl);
5730 	const char *s = IDENTIFIER_POINTER (name_tree);
5731 	size_t len = strlen (s);
5732 	if (len > 4 && (strncmp (s, "__builtin_GOMP_", 15) == 0))
5733 	  HSA_SORRY_ATV (gimple_location (stmt),
5734 			 "support for HSA does not implement GOMP function %s",
5735 			 s);
5736 	else
5737 	  gen_hsa_insns_for_direct_call (stmt, hbb);
5738 	return;
5739       }
5740     }
5741 }
5742 
5743 /* Generate HSA instructions for a given gimple statement.  Instructions will be
5744    appended to HBB.  */
5745 
5746 static void
gen_hsa_insns_for_gimple_stmt(gimple * stmt,hsa_bb * hbb)5747 gen_hsa_insns_for_gimple_stmt (gimple *stmt, hsa_bb *hbb)
5748 {
5749   switch (gimple_code (stmt))
5750     {
5751     case GIMPLE_ASSIGN:
5752       if (gimple_clobber_p (stmt))
5753 	break;
5754 
5755       if (gimple_assign_single_p (stmt))
5756 	{
5757 	  tree lhs = gimple_assign_lhs (stmt);
5758 	  tree rhs = gimple_assign_rhs1 (stmt);
5759 	  gen_hsa_insns_for_single_assignment (lhs, rhs, hbb);
5760 	}
5761       else
5762 	gen_hsa_insns_for_operation_assignment (stmt, hbb);
5763       break;
5764     case GIMPLE_RETURN:
5765       gen_hsa_insns_for_return (as_a <greturn *> (stmt), hbb);
5766       break;
5767     case GIMPLE_COND:
5768       gen_hsa_insns_for_cond_stmt (stmt, hbb);
5769       break;
5770     case GIMPLE_CALL:
5771       gen_hsa_insns_for_call (stmt, hbb);
5772       break;
5773     case GIMPLE_DEBUG:
5774       /* ??? HSA supports some debug facilities.  */
5775       break;
5776     case GIMPLE_LABEL:
5777     {
5778       tree label = gimple_label_label (as_a <glabel *> (stmt));
5779       if (FORCED_LABEL (label))
5780 	HSA_SORRY_AT (gimple_location (stmt),
5781 		      "support for HSA does not implement gimple label with "
5782 		      "address taken");
5783 
5784       break;
5785     }
5786     case GIMPLE_NOP:
5787     {
5788       hbb->append_insn (new hsa_insn_basic (0, BRIG_OPCODE_NOP));
5789       break;
5790     }
5791     case GIMPLE_SWITCH:
5792     {
5793       gen_hsa_insns_for_switch_stmt (as_a <gswitch *> (stmt), hbb);
5794       break;
5795     }
5796     default:
5797       HSA_SORRY_ATV (gimple_location (stmt),
5798 		     "support for HSA does not implement gimple statement %s",
5799 		     gimple_code_name[(int) gimple_code (stmt)]);
5800     }
5801 }
5802 
5803 /* Generate a HSA PHI from a gimple PHI.  */
5804 
5805 static void
gen_hsa_phi_from_gimple_phi(gimple * phi_stmt,hsa_bb * hbb)5806 gen_hsa_phi_from_gimple_phi (gimple *phi_stmt, hsa_bb *hbb)
5807 {
5808   hsa_insn_phi *hphi;
5809   unsigned count = gimple_phi_num_args (phi_stmt);
5810 
5811   hsa_op_reg *dest
5812     = hsa_cfun->reg_for_gimple_ssa (gimple_phi_result (phi_stmt));
5813   hphi = new hsa_insn_phi (count, dest);
5814   hphi->m_bb = hbb->m_bb;
5815 
5816   auto_vec <tree, 8> aexprs;
5817   auto_vec <hsa_op_reg *, 8> aregs;
5818 
5819   /* Calling split_edge when processing a PHI node messes up with the order of
5820      gimple phi node arguments (it moves the one associated with the edge to
5821      the end).  We need to keep the order of edges and arguments of HSA phi
5822      node arguments consistent, so we do all required splitting as the first
5823      step, and in reverse order as to not be affected by the re-orderings.  */
5824   for (unsigned j = count; j != 0; j--)
5825     {
5826       unsigned i = j - 1;
5827       tree op = gimple_phi_arg_def (phi_stmt, i);
5828       if (TREE_CODE (op) != ADDR_EXPR)
5829 	continue;
5830 
5831       edge e = gimple_phi_arg_edge (as_a <gphi *> (phi_stmt), i);
5832       hsa_bb *hbb_src = hsa_init_new_bb (split_edge (e));
5833       hsa_op_address *addr = gen_hsa_addr (TREE_OPERAND (op, 0),
5834 					   hbb_src);
5835 
5836       hsa_op_reg *dest
5837 	= new hsa_op_reg (hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT));
5838       hsa_insn_basic *insn
5839 	= new hsa_insn_basic (2, BRIG_OPCODE_LDA, BRIG_TYPE_U64,
5840 			      dest, addr);
5841       hbb_src->append_insn (insn);
5842       aexprs.safe_push (op);
5843       aregs.safe_push (dest);
5844     }
5845 
5846   tree lhs = gimple_phi_result (phi_stmt);
5847   for (unsigned i = 0; i < count; i++)
5848     {
5849       tree op = gimple_phi_arg_def (phi_stmt, i);
5850 
5851       if (TREE_CODE (op) == SSA_NAME)
5852 	{
5853 	  hsa_op_reg *hreg = hsa_cfun->reg_for_gimple_ssa (op);
5854 	  hphi->set_op (i, hreg);
5855 	}
5856       else
5857 	{
5858 	  gcc_assert (is_gimple_min_invariant (op));
5859 	  tree t = TREE_TYPE (op);
5860 	  if (!POINTER_TYPE_P (t)
5861 	      || (TREE_CODE (op) == STRING_CST
5862 		  && TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE))
5863 	    hphi->set_op (i, new hsa_op_immed (op));
5864 	  else if (POINTER_TYPE_P (TREE_TYPE (lhs))
5865 		   && TREE_CODE (op) == INTEGER_CST)
5866 	    {
5867 	      /* Handle assignment of NULL value to a pointer type.  */
5868 	      hphi->set_op (i, new hsa_op_immed (op));
5869 	    }
5870 	  else if (TREE_CODE (op) == ADDR_EXPR)
5871 	    {
5872 	      hsa_op_reg *dest = NULL;
5873 	      for (unsigned a_idx = 0; a_idx < aexprs.length (); a_idx++)
5874 		if (aexprs[a_idx] == op)
5875 		  {
5876 		    dest = aregs[a_idx];
5877 		    break;
5878 		  }
5879 	      gcc_assert (dest);
5880 	      hphi->set_op (i, dest);
5881 	    }
5882 	  else
5883 	    {
5884 	      HSA_SORRY_AT (gimple_location (phi_stmt),
5885 			    "support for HSA does not handle PHI nodes with "
5886 			    "constant address operands");
5887 	      return;
5888 	    }
5889 	}
5890     }
5891 
5892   hbb->append_phi (hphi);
5893 }
5894 
5895 /* Constructor of class containing HSA-specific information about a basic
5896    block.  CFG_BB is the CFG BB this HSA BB is associated with.  IDX is the new
5897    index of this BB (so that the constructor does not attempt to use
5898    hsa_cfun during its construction).  */
5899 
hsa_bb(basic_block cfg_bb,int idx)5900 hsa_bb::hsa_bb (basic_block cfg_bb, int idx)
5901   : m_bb (cfg_bb), m_first_insn (NULL), m_last_insn (NULL), m_first_phi (NULL),
5902     m_last_phi (NULL), m_index (idx)
5903 {
5904   gcc_assert (!cfg_bb->aux);
5905   cfg_bb->aux = this;
5906 }
5907 
5908 /* Constructor of class containing HSA-specific information about a basic
5909    block.  CFG_BB is the CFG BB this HSA BB is associated with.  */
5910 
hsa_bb(basic_block cfg_bb)5911 hsa_bb::hsa_bb (basic_block cfg_bb)
5912   : m_bb (cfg_bb), m_first_insn (NULL), m_last_insn (NULL), m_first_phi (NULL),
5913     m_last_phi (NULL), m_index (hsa_cfun->m_hbb_count++)
5914 {
5915   gcc_assert (!cfg_bb->aux);
5916   cfg_bb->aux = this;
5917 }
5918 
5919 /* Create and initialize and return a new hsa_bb structure for a given CFG
5920    basic block BB.  */
5921 
5922 hsa_bb *
hsa_init_new_bb(basic_block bb)5923 hsa_init_new_bb (basic_block bb)
5924 {
5925   void *m = obstack_alloc (&hsa_obstack, sizeof (hsa_bb));
5926   return new (m) hsa_bb (bb);
5927 }
5928 
5929 /* Initialize OMP in an HSA basic block PROLOGUE.  */
5930 
5931 static void
init_prologue(void)5932 init_prologue (void)
5933 {
5934   if (!hsa_cfun->m_kern_p)
5935     return;
5936 
5937   hsa_bb *prologue = hsa_bb_for_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun));
5938 
5939   /* Create a magic number that is going to be printed by libgomp.  */
5940   unsigned index = hsa_get_number_decl_kernel_mappings ();
5941 
5942   /* Emit store to debug argument.  */
5943   if (param_hsa_gen_debug_stores > 0)
5944     set_debug_value (prologue, new hsa_op_immed (1000 + index, BRIG_TYPE_U64));
5945 }
5946 
5947 /* Initialize hsa_num_threads to a default value.  */
5948 
5949 static void
init_hsa_num_threads(void)5950 init_hsa_num_threads (void)
5951 {
5952   hsa_bb *prologue = hsa_bb_for_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun));
5953 
5954   /* Save the default value to private variable hsa_num_threads.  */
5955   hsa_insn_basic *basic
5956     = new hsa_insn_mem (BRIG_OPCODE_ST, hsa_num_threads->m_type,
5957 			new hsa_op_immed (0, hsa_num_threads->m_type),
5958 			new hsa_op_address (hsa_num_threads));
5959   prologue->append_insn (basic);
5960 }
5961 
5962 /* Go over gimple representation and generate our internal HSA one.  */
5963 
5964 static void
gen_body_from_gimple()5965 gen_body_from_gimple ()
5966 {
5967   basic_block bb;
5968 
5969   /* Verify CFG for complex edges we are unable to handle.  */
5970   edge_iterator ei;
5971   edge e;
5972 
5973   FOR_EACH_BB_FN (bb, cfun)
5974     {
5975       FOR_EACH_EDGE (e, ei, bb->succs)
5976 	{
5977 	  /* Verify all unsupported flags for edges that point
5978 	     to the same basic block.  */
5979 	  if (e->flags & EDGE_EH)
5980 	    {
5981 	      HSA_SORRY_AT (UNKNOWN_LOCATION,
5982 			    "support for HSA does not implement exception "
5983 			    "handling");
5984 	      return;
5985 	    }
5986 	}
5987     }
5988 
5989   FOR_EACH_BB_FN (bb, cfun)
5990     {
5991       gimple_stmt_iterator gsi;
5992       hsa_bb *hbb = hsa_bb_for_bb (bb);
5993       if (hbb)
5994 	continue;
5995 
5996       hbb = hsa_init_new_bb (bb);
5997 
5998       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
5999 	{
6000 	  gen_hsa_insns_for_gimple_stmt (gsi_stmt (gsi), hbb);
6001 	  if (hsa_seen_error ())
6002 	    return;
6003 	}
6004     }
6005 
6006   FOR_EACH_BB_FN (bb, cfun)
6007     {
6008       gimple_stmt_iterator gsi;
6009       hsa_bb *hbb = hsa_bb_for_bb (bb);
6010       gcc_assert (hbb != NULL);
6011 
6012       for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
6013 	if (!virtual_operand_p (gimple_phi_result (gsi_stmt (gsi))))
6014 	  gen_hsa_phi_from_gimple_phi (gsi_stmt (gsi), hbb);
6015     }
6016 
6017   if (dump_file && (dump_flags & TDF_DETAILS))
6018     {
6019       fprintf (dump_file, "------- Generated SSA form -------\n");
6020       dump_hsa_cfun (dump_file);
6021     }
6022 }
6023 
6024 static void
gen_function_decl_parameters(hsa_function_representation * f,tree decl)6025 gen_function_decl_parameters (hsa_function_representation *f,
6026 			      tree decl)
6027 {
6028   tree parm;
6029   unsigned i;
6030 
6031   for (parm = TYPE_ARG_TYPES (TREE_TYPE (decl)), i = 0;
6032        parm;
6033        parm = TREE_CHAIN (parm), i++)
6034     {
6035       /* Result type if last in the tree list.  */
6036       if (TREE_CHAIN (parm) == NULL)
6037 	break;
6038 
6039       tree v = TREE_VALUE (parm);
6040 
6041       hsa_symbol *arg = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_ARG,
6042 					BRIG_LINKAGE_NONE);
6043       arg->m_type = hsa_type_for_tree_type (v, &arg->m_dim);
6044       arg->m_name_number = i;
6045 
6046       f->m_input_args.safe_push (arg);
6047     }
6048 
6049   tree result_type = TREE_TYPE (TREE_TYPE (decl));
6050   if (!VOID_TYPE_P (result_type))
6051     {
6052       f->m_output_arg = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_ARG,
6053 					BRIG_LINKAGE_NONE);
6054       f->m_output_arg->m_type
6055 	= hsa_type_for_tree_type (result_type, &f->m_output_arg->m_dim);
6056       f->m_output_arg->m_name = "res";
6057     }
6058 }
6059 
6060 /* Generate the vector of parameters of the HSA representation of the current
6061    function.  This also includes the output parameter representing the
6062    result.  */
6063 
6064 static void
gen_function_def_parameters()6065 gen_function_def_parameters ()
6066 {
6067   tree parm;
6068 
6069   hsa_bb *prologue = hsa_bb_for_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun));
6070 
6071   for (parm = DECL_ARGUMENTS (cfun->decl); parm;
6072        parm = DECL_CHAIN (parm))
6073     {
6074       class hsa_symbol **slot;
6075 
6076       hsa_symbol *arg
6077 	= new hsa_symbol (BRIG_TYPE_NONE, hsa_cfun->m_kern_p
6078 			  ? BRIG_SEGMENT_KERNARG : BRIG_SEGMENT_ARG,
6079 			  BRIG_LINKAGE_FUNCTION);
6080       arg->fillup_for_decl (parm);
6081 
6082       hsa_cfun->m_input_args.safe_push (arg);
6083 
6084       if (hsa_seen_error ())
6085 	return;
6086 
6087       arg->m_name = hsa_get_declaration_name (parm);
6088 
6089       /* Copy all input arguments and create corresponding private symbols
6090 	 for them.  */
6091       hsa_symbol *private_arg;
6092       hsa_op_address *parm_addr = new hsa_op_address (arg);
6093 
6094       if (TREE_ADDRESSABLE (parm)
6095 	  || (!is_gimple_reg (parm) && !TREE_READONLY (parm)))
6096 	{
6097 	  private_arg = hsa_cfun->create_hsa_temporary (arg->m_type);
6098 	  private_arg->fillup_for_decl (parm);
6099 
6100 	  BrigAlignment8_t align = MIN (arg->m_align, private_arg->m_align);
6101 
6102 	  hsa_op_address *private_arg_addr = new hsa_op_address (private_arg);
6103 	  gen_hsa_memory_copy (prologue, private_arg_addr, parm_addr,
6104 			       arg->total_byte_size (), align);
6105 	}
6106       else
6107 	private_arg = arg;
6108 
6109       slot = hsa_cfun->m_local_symbols->find_slot (private_arg, INSERT);
6110       gcc_assert (!*slot);
6111       *slot = private_arg;
6112 
6113       if (is_gimple_reg (parm))
6114 	{
6115 	  tree ddef = ssa_default_def (cfun, parm);
6116 	  if (ddef && !has_zero_uses (ddef))
6117 	    {
6118 	      BrigType16_t t = hsa_type_for_scalar_tree_type (TREE_TYPE (ddef),
6119 							      false);
6120 	      BrigType16_t mtype = mem_type_for_type (t);
6121 	      hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (ddef);
6122 	      hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, mtype,
6123 						    dest, parm_addr);
6124 	      gcc_assert (!parm_addr->m_reg);
6125 	      prologue->append_insn (mem);
6126 	    }
6127 	}
6128     }
6129 
6130   if (!VOID_TYPE_P (TREE_TYPE (TREE_TYPE (cfun->decl))))
6131     {
6132       class hsa_symbol **slot;
6133 
6134       hsa_cfun->m_output_arg = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_ARG,
6135 					       BRIG_LINKAGE_FUNCTION);
6136       hsa_cfun->m_output_arg->fillup_for_decl (DECL_RESULT (cfun->decl));
6137 
6138       if (hsa_seen_error ())
6139 	return;
6140 
6141       hsa_cfun->m_output_arg->m_name = "res";
6142       slot = hsa_cfun->m_local_symbols->find_slot (hsa_cfun->m_output_arg,
6143 						   INSERT);
6144       gcc_assert (!*slot);
6145       *slot = hsa_cfun->m_output_arg;
6146     }
6147 }
6148 
6149 /* Generate function representation that corresponds to
6150    a function declaration.  */
6151 
6152 hsa_function_representation *
hsa_generate_function_declaration(tree decl)6153 hsa_generate_function_declaration (tree decl)
6154 {
6155   hsa_function_representation *fun
6156     = new hsa_function_representation (decl, false, 0);
6157 
6158   fun->m_declaration_p = true;
6159   fun->m_name = get_brig_function_name (decl);
6160   gen_function_decl_parameters (fun, decl);
6161 
6162   return fun;
6163 }
6164 
6165 
6166 /* Generate function representation that corresponds to
6167    an internal FN.  */
6168 
6169 hsa_function_representation *
hsa_generate_internal_fn_decl(hsa_internal_fn * fn)6170 hsa_generate_internal_fn_decl (hsa_internal_fn *fn)
6171 {
6172   hsa_function_representation *fun = new hsa_function_representation (fn);
6173 
6174   fun->m_name = fn->name ();
6175 
6176   for (unsigned i = 0; i < fn->get_arity (); i++)
6177     {
6178       hsa_symbol *arg
6179 	= new hsa_symbol (fn->get_argument_type (i), BRIG_SEGMENT_ARG,
6180 			  BRIG_LINKAGE_NONE);
6181       arg->m_name_number = i;
6182       fun->m_input_args.safe_push (arg);
6183     }
6184 
6185   fun->m_output_arg = new hsa_symbol (fn->get_argument_type (-1),
6186 				      BRIG_SEGMENT_ARG, BRIG_LINKAGE_NONE);
6187   fun->m_output_arg->m_name = "res";
6188 
6189   return fun;
6190 }
6191 
6192 /* Return true if switch statement S can be transformed
6193    to a SBR instruction in HSAIL.  */
6194 
6195 static bool
transformable_switch_to_sbr_p(gswitch * s)6196 transformable_switch_to_sbr_p (gswitch *s)
6197 {
6198   /* Identify if a switch statement can be transformed to
6199      SBR instruction, like:
6200 
6201      sbr_u32 $s1 [@label1, @label2, @label3];
6202   */
6203 
6204   tree size = get_switch_size (s);
6205   if (!tree_fits_uhwi_p (size))
6206     return false;
6207 
6208   if (tree_to_uhwi (size) > HSA_MAXIMUM_SBR_LABELS)
6209     return false;
6210 
6211   return true;
6212 }
6213 
6214 /* Structure hold connection between PHI nodes and immediate
6215    values hold by there nodes.  */
6216 
6217 class phi_definition
6218 {
6219 public:
phi_definition(unsigned phi_i,unsigned label_i,tree imm)6220   phi_definition (unsigned phi_i, unsigned label_i, tree imm):
6221     phi_index (phi_i), label_index (label_i), phi_value (imm)
6222   {}
6223 
6224   unsigned phi_index;
6225   unsigned label_index;
6226   tree phi_value;
6227 };
6228 
6229 /* Sum slice of a vector V, starting from index START and ending
6230    at the index END - 1.  */
6231 
6232 template <typename T>
6233 static
sum_slice(const auto_vec<T> & v,unsigned start,unsigned end,T zero)6234 T sum_slice (const auto_vec <T> &v, unsigned start, unsigned end,
6235 	     T zero)
6236 {
6237   T s = zero;
6238 
6239   for (unsigned i = start; i < end; i++)
6240     s += v[i];
6241 
6242   return s;
6243 }
6244 
6245 /* Function transforms GIMPLE SWITCH statements to a series of IF statements.
6246    Let's assume following example:
6247 
6248 L0:
6249    switch (index)
6250      case C1:
6251 L1:    hard_work_1 ();
6252        break;
6253      case C2..C3:
6254 L2:    hard_work_2 ();
6255        break;
6256      default:
6257 LD:    hard_work_3 ();
6258        break;
6259 
6260   The transformation encompasses following steps:
6261     1) all immediate values used by edges coming from the switch basic block
6262        are saved
6263     2) all these edges are removed
6264     3) the switch statement (in L0) is replaced by:
6265 	 if (index == C1)
6266 	   goto L1;
6267 	 else
6268 	   goto L1';
6269 
6270     4) newly created basic block Lx' is used for generation of
6271        a next condition
6272     5) else branch of the last condition goes to LD
6273     6) fix all immediate values in PHI nodes that were propagated though
6274        edges that were removed in step 2
6275 
6276   Note: if a case is made by a range C1..C2, then process
6277 	following transformation:
6278 
6279   switch_cond_op1 = C1 <= index;
6280   switch_cond_op2 = index <= C2;
6281   switch_cond_and = switch_cond_op1 & switch_cond_op2;
6282   if (switch_cond_and != 0)
6283     goto Lx;
6284   else
6285     goto Ly;
6286 
6287 */
6288 
6289 static bool
convert_switch_statements(void)6290 convert_switch_statements (void)
6291 {
6292   basic_block bb;
6293 
6294   bool modified_cfg = false;
6295 
6296   FOR_EACH_BB_FN (bb, cfun)
6297   {
6298     gimple_stmt_iterator gsi = gsi_last_bb (bb);
6299     if (gsi_end_p (gsi))
6300       continue;
6301 
6302     gimple *stmt = gsi_stmt (gsi);
6303 
6304     if (gimple_code (stmt) == GIMPLE_SWITCH)
6305       {
6306 	gswitch *s = as_a <gswitch *> (stmt);
6307 
6308 	/* If the switch can utilize SBR insn, skip the statement.  */
6309 	if (transformable_switch_to_sbr_p (s))
6310 	  continue;
6311 
6312 	modified_cfg = true;
6313 
6314 	unsigned labels = gimple_switch_num_labels (s);
6315 	tree index = gimple_switch_index (s);
6316 	tree index_type = TREE_TYPE (index);
6317 	tree default_label = gimple_switch_default_label (s);
6318 	basic_block default_label_bb
6319 	  = label_to_block (cfun, CASE_LABEL (default_label));
6320 	basic_block cur_bb = bb;
6321 
6322 	auto_vec <edge> new_edges;
6323 	auto_vec <phi_definition *> phi_todo_list;
6324 	auto_vec <profile_count> edge_counts;
6325 	auto_vec <profile_probability> edge_probabilities;
6326 
6327 	/* Investigate all labels that and PHI nodes in these edges which
6328 	   should be fixed after we add new collection of edges.  */
6329 	for (unsigned i = 0; i < labels; i++)
6330 	  {
6331 	    basic_block label_bb = gimple_switch_label_bb (cfun, s, i);
6332 	    edge e = find_edge (bb, label_bb);
6333 	    edge_counts.safe_push (e->count ());
6334 	    edge_probabilities.safe_push (e->probability);
6335 	    gphi_iterator phi_gsi;
6336 
6337 	    /* Save PHI definitions that will be destroyed because of an edge
6338 	       is going to be removed.  */
6339 	    unsigned phi_index = 0;
6340 	    for (phi_gsi = gsi_start_phis (e->dest);
6341 		 !gsi_end_p (phi_gsi); gsi_next (&phi_gsi))
6342 	      {
6343 		gphi *phi = phi_gsi.phi ();
6344 		for (unsigned j = 0; j < gimple_phi_num_args (phi); j++)
6345 		  {
6346 		    if (gimple_phi_arg_edge (phi, j) == e)
6347 		      {
6348 			tree imm = gimple_phi_arg_def (phi, j);
6349 			phi_definition *p = new phi_definition (phi_index, i,
6350 								imm);
6351 			phi_todo_list.safe_push (p);
6352 			break;
6353 		      }
6354 		  }
6355 		phi_index++;
6356 	      }
6357 	  }
6358 
6359 	/* Remove all edges for the current basic block.  */
6360 	for (int i = EDGE_COUNT (bb->succs) - 1; i >= 0; i--)
6361  	  {
6362 	    edge e = EDGE_SUCC (bb, i);
6363 	    remove_edge (e);
6364 	  }
6365 
6366 	/* Iterate all non-default labels.  */
6367 	for (unsigned i = 1; i < labels; i++)
6368 	  {
6369 	    tree label = gimple_switch_label (s, i);
6370 	    tree low = CASE_LOW (label);
6371 	    tree high = CASE_HIGH (label);
6372 
6373 	    if (!useless_type_conversion_p (TREE_TYPE (low), index_type))
6374 	      low = fold_convert (index_type, low);
6375 
6376 	    gimple_stmt_iterator cond_gsi = gsi_last_bb (cur_bb);
6377 	    gimple *c = NULL;
6378 	    if (high)
6379 	      {
6380 		tree tmp1 = make_temp_ssa_name (boolean_type_node, NULL,
6381 						"switch_cond_op1");
6382 
6383 		gimple *assign1 = gimple_build_assign (tmp1, LE_EXPR, low,
6384 						      index);
6385 
6386 		tree tmp2 = make_temp_ssa_name (boolean_type_node, NULL,
6387 						"switch_cond_op2");
6388 
6389 		if (!useless_type_conversion_p (TREE_TYPE (high), index_type))
6390 		  high = fold_convert (index_type, high);
6391 		gimple *assign2 = gimple_build_assign (tmp2, LE_EXPR, index,
6392 						      high);
6393 
6394 		tree tmp3 = make_temp_ssa_name (boolean_type_node, NULL,
6395 						"switch_cond_and");
6396 		gimple *assign3 = gimple_build_assign (tmp3, BIT_AND_EXPR, tmp1,
6397 						      tmp2);
6398 
6399 		gsi_insert_before (&cond_gsi, assign1, GSI_SAME_STMT);
6400 		gsi_insert_before (&cond_gsi, assign2, GSI_SAME_STMT);
6401 		gsi_insert_before (&cond_gsi, assign3, GSI_SAME_STMT);
6402 
6403 		tree b = constant_boolean_node (false, boolean_type_node);
6404 		c = gimple_build_cond (NE_EXPR, tmp3, b, NULL, NULL);
6405 	      }
6406 	    else
6407 	      c = gimple_build_cond (EQ_EXPR, index, low, NULL, NULL);
6408 
6409 	    gimple_set_location (c, gimple_location (stmt));
6410 
6411 	    gsi_insert_before (&cond_gsi, c, GSI_SAME_STMT);
6412 
6413 	    basic_block label_bb = label_to_block (cfun, CASE_LABEL (label));
6414 	    edge new_edge = make_edge (cur_bb, label_bb, EDGE_TRUE_VALUE);
6415 	    profile_probability prob_sum = sum_slice <profile_probability>
6416 		 (edge_probabilities, i, labels, profile_probability::never ())
6417 		  + edge_probabilities[0];
6418 
6419 	    if (prob_sum.initialized_p ())
6420 	      new_edge->probability = edge_probabilities[i] / prob_sum;
6421 
6422 	    new_edges.safe_push (new_edge);
6423 
6424 	    if (i < labels - 1)
6425 	      {
6426 		/* Prepare another basic block that will contain
6427 		   next condition.  */
6428 		basic_block next_bb = create_empty_bb (cur_bb);
6429 		if (current_loops)
6430 		  {
6431 		    add_bb_to_loop (next_bb, cur_bb->loop_father);
6432 		    loops_state_set (LOOPS_NEED_FIXUP);
6433 		  }
6434 
6435 		edge next_edge = make_edge (cur_bb, next_bb, EDGE_FALSE_VALUE);
6436 		next_edge->probability = new_edge->probability.invert ();
6437 		next_bb->count = next_edge->count ();
6438 		cur_bb = next_bb;
6439 	      }
6440 	    else /* Link last IF statement and default label
6441 		    of the switch.  */
6442 	      {
6443 		edge e = make_edge (cur_bb, default_label_bb, EDGE_FALSE_VALUE);
6444 		e->probability = new_edge->probability.invert ();
6445 		new_edges.safe_insert (0, e);
6446 	      }
6447 	  }
6448 
6449 	  /* Restore original PHI immediate value.  */
6450 	  for (unsigned i = 0; i < phi_todo_list.length (); i++)
6451 	    {
6452 	      phi_definition *phi_def = phi_todo_list[i];
6453 	      edge new_edge = new_edges[phi_def->label_index];
6454 
6455 	      gphi_iterator it = gsi_start_phis (new_edge->dest);
6456 	      for (unsigned i = 0; i < phi_def->phi_index; i++)
6457 		gsi_next (&it);
6458 
6459 	      gphi *phi = it.phi ();
6460 	      add_phi_arg (phi, phi_def->phi_value, new_edge, UNKNOWN_LOCATION);
6461 	      delete phi_def;
6462 	    }
6463 
6464 	/* Remove the original GIMPLE switch statement.  */
6465 	gsi_remove (&gsi, true);
6466       }
6467   }
6468 
6469   if (dump_file)
6470     dump_function_to_file (current_function_decl, dump_file, TDF_DETAILS);
6471 
6472   return modified_cfg;
6473 }
6474 
6475 /* Expand builtins that can't be handled by HSA back-end.  */
6476 
6477 static void
expand_builtins()6478 expand_builtins ()
6479 {
6480   basic_block bb;
6481 
6482   FOR_EACH_BB_FN (bb, cfun)
6483   {
6484     for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
6485 	 gsi_next (&gsi))
6486       {
6487 	gimple *stmt = gsi_stmt (gsi);
6488 
6489 	if (gimple_code (stmt) != GIMPLE_CALL)
6490 	  continue;
6491 
6492 	gcall *call = as_a <gcall *> (stmt);
6493 
6494 	if (!gimple_call_builtin_p (call, BUILT_IN_NORMAL))
6495 	  continue;
6496 
6497 	tree fndecl = gimple_call_fndecl (stmt);
6498 	enum built_in_function fn = DECL_FUNCTION_CODE (fndecl);
6499 	switch (fn)
6500 	  {
6501 	  case BUILT_IN_CEXPF:
6502 	  case BUILT_IN_CEXPIF:
6503 	  case BUILT_IN_CEXPI:
6504 	    {
6505 	      /* Similar to builtins.c (expand_builtin_cexpi), the builtin
6506 		 can be transformed to: cexp(I * z) = ccos(z) + I * csin(z).  */
6507 	      tree lhs = gimple_call_lhs (stmt);
6508 	      tree rhs = gimple_call_arg (stmt, 0);
6509 	      tree rhs_type = TREE_TYPE (rhs);
6510 	      bool float_type_p = rhs_type == float_type_node;
6511 	      tree real_part = make_temp_ssa_name (rhs_type, NULL,
6512 						   "cexp_real_part");
6513 	      tree imag_part = make_temp_ssa_name (rhs_type, NULL,
6514 						   "cexp_imag_part");
6515 
6516 	      tree cos_fndecl
6517 		= mathfn_built_in (rhs_type, fn == float_type_p
6518 				   ? BUILT_IN_COSF : BUILT_IN_COS);
6519 	      gcall *cos = gimple_build_call (cos_fndecl, 1, rhs);
6520 	      gimple_call_set_lhs (cos, real_part);
6521 	      gsi_insert_before (&gsi, cos, GSI_SAME_STMT);
6522 
6523 	      tree sin_fndecl
6524 		= mathfn_built_in (rhs_type, fn == float_type_p
6525 				   ? BUILT_IN_SINF : BUILT_IN_SIN);
6526 	      gcall *sin = gimple_build_call (sin_fndecl, 1, rhs);
6527 	      gimple_call_set_lhs (sin, imag_part);
6528 	      gsi_insert_before (&gsi, sin, GSI_SAME_STMT);
6529 
6530 
6531 	      gassign *assign = gimple_build_assign (lhs, COMPLEX_EXPR,
6532 						     real_part, imag_part);
6533 	      gsi_insert_before (&gsi, assign, GSI_SAME_STMT);
6534 	      gsi_remove (&gsi, true);
6535 
6536 	      break;
6537 	    }
6538 	  default:
6539 	    break;
6540 	  }
6541       }
6542   }
6543 }
6544 
6545 /* Emit HSA module variables that are global for the entire module.  */
6546 
6547 static void
emit_hsa_module_variables(void)6548 emit_hsa_module_variables (void)
6549 {
6550   hsa_num_threads = new hsa_symbol (BRIG_TYPE_U32, BRIG_SEGMENT_PRIVATE,
6551 				    BRIG_LINKAGE_MODULE, true);
6552 
6553   hsa_num_threads->m_name = "hsa_num_threads";
6554 
6555   hsa_brig_emit_omp_symbols ();
6556 }
6557 
6558 /* Generate HSAIL representation of the current function and write into a
6559    special section of the output file.  If KERNEL is set, the function will be
6560    considered an HSA kernel callable from the host, otherwise it will be
6561    compiled as an HSA function callable from other HSA code.  */
6562 
6563 static void
generate_hsa(bool kernel)6564 generate_hsa (bool kernel)
6565 {
6566   hsa_init_data_for_cfun ();
6567 
6568   if (hsa_num_threads == NULL)
6569     emit_hsa_module_variables ();
6570 
6571   bool modified_cfg = convert_switch_statements ();
6572   /* Initialize hsa_cfun.  */
6573   hsa_cfun = new hsa_function_representation (cfun->decl, kernel,
6574 					      SSANAMES (cfun)->length (),
6575 					      modified_cfg);
6576   hsa_cfun->init_extra_bbs ();
6577 
6578   if (flag_tm)
6579     {
6580       HSA_SORRY_AT (UNKNOWN_LOCATION,
6581 		    "support for HSA does not implement transactional memory");
6582       goto fail;
6583     }
6584 
6585   verify_function_arguments (cfun->decl);
6586   if (hsa_seen_error ())
6587     goto fail;
6588 
6589   hsa_cfun->m_name = get_brig_function_name (cfun->decl);
6590 
6591   gen_function_def_parameters ();
6592   if (hsa_seen_error ())
6593     goto fail;
6594 
6595   init_prologue ();
6596 
6597   gen_body_from_gimple ();
6598   if (hsa_seen_error ())
6599     goto fail;
6600 
6601   if (hsa_cfun->m_kernel_dispatch_count)
6602     init_hsa_num_threads ();
6603 
6604   if (hsa_cfun->m_kern_p)
6605     {
6606       hsa_function_summary *s
6607 	= hsa_summaries->get_create (cgraph_node::get (hsa_cfun->m_decl));
6608       hsa_add_kern_decl_mapping (current_function_decl, hsa_cfun->m_name,
6609 				 hsa_cfun->m_maximum_omp_data_size,
6610 				 s->m_gridified_kernel_p);
6611     }
6612 
6613   if (flag_checking)
6614     {
6615       for (unsigned i = 0; i < hsa_cfun->m_ssa_map.length (); i++)
6616 	if (hsa_cfun->m_ssa_map[i])
6617 	  hsa_cfun->m_ssa_map[i]->verify_ssa ();
6618 
6619       basic_block bb;
6620       FOR_EACH_BB_FN (bb, cfun)
6621 	{
6622 	  hsa_bb *hbb = hsa_bb_for_bb (bb);
6623 
6624 	  for (hsa_insn_basic *insn = hbb->m_first_insn; insn;
6625 	       insn = insn->m_next)
6626 	    insn->verify ();
6627 	}
6628     }
6629 
6630   hsa_regalloc ();
6631   hsa_brig_emit_function ();
6632 
6633  fail:
6634   hsa_deinit_data_for_cfun ();
6635 }
6636 
6637 namespace {
6638 
6639 const pass_data pass_data_gen_hsail =
6640 {
6641   GIMPLE_PASS,
6642   "hsagen",	 			/* name */
6643   OPTGROUP_OMP,				/* optinfo_flags */
6644   TV_NONE,				/* tv_id */
6645   PROP_cfg | PROP_ssa,			/* properties_required */
6646   0,					/* properties_provided */
6647   0,					/* properties_destroyed */
6648   0,					/* todo_flags_start */
6649   0					/* todo_flags_finish */
6650 };
6651 
6652 class pass_gen_hsail : public gimple_opt_pass
6653 {
6654 public:
pass_gen_hsail(gcc::context * ctxt)6655   pass_gen_hsail (gcc::context *ctxt)
6656     : gimple_opt_pass(pass_data_gen_hsail, ctxt)
6657   {}
6658 
6659   /* opt_pass methods: */
6660   bool gate (function *);
6661   unsigned int execute (function *);
6662 
6663 }; // class pass_gen_hsail
6664 
6665 /* Determine whether or not to run generation of HSAIL.  */
6666 
6667 bool
gate(function * f)6668 pass_gen_hsail::gate (function *f)
6669 {
6670   return hsa_gen_requested_p ()
6671     && hsa_gpu_implementation_p (f->decl);
6672 }
6673 
6674 unsigned int
execute(function *)6675 pass_gen_hsail::execute (function *)
6676 {
6677   cgraph_node *node = cgraph_node::get_create (current_function_decl);
6678   hsa_function_summary *s = hsa_summaries->get_create (node);
6679 
6680   expand_builtins ();
6681   generate_hsa (s->m_kind == HSA_KERNEL);
6682   TREE_ASM_WRITTEN (current_function_decl) = 1;
6683   return TODO_discard_function;
6684 }
6685 
6686 } // anon namespace
6687 
6688 /* Create the instance of hsa gen pass.  */
6689 
6690 gimple_opt_pass *
make_pass_gen_hsail(gcc::context * ctxt)6691 make_pass_gen_hsail (gcc::context *ctxt)
6692 {
6693   return new pass_gen_hsail (ctxt);
6694 }
6695