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