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