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