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