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