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