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